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.

3981 lines
88 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1998
  6. //
  7. // File: cepca.cpp
  8. //
  9. // Contents: Cisco enrollment protocal implementation.
  10. // This file has the control's (ra) specific code.
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "global.hxx"
  14. #include <dbgdef.h>
  15. //--------------------------------------------------------------------------
  16. //
  17. // FreeRAInformation
  18. //
  19. //--------------------------------------------------------------------------
  20. BOOL FreeRAInformation(CEP_RA_INFO *pRAInfo)
  21. {
  22. if(pRAInfo)
  23. {
  24. if(pRAInfo->fFree)
  25. {
  26. if(pRAInfo->hRAProv)
  27. CryptReleaseContext(pRAInfo->hRAProv, 0);
  28. }
  29. if(pRAInfo->fSignFree)
  30. {
  31. if(pRAInfo->hSignProv)
  32. CryptReleaseContext(pRAInfo->hSignProv, 0);
  33. }
  34. if(pRAInfo->pRACert)
  35. CertFreeCertificateContext(pRAInfo->pRACert);
  36. if(pRAInfo->pRASign)
  37. CertFreeCertificateContext(pRAInfo->pRASign);
  38. memset(pRAInfo, 0, sizeof(CEP_RA_INFO));
  39. }
  40. return TRUE;
  41. }
  42. /*
  43. //--------------------------------------------------------------------------
  44. //
  45. // GetRAInfo
  46. //
  47. //--------------------------------------------------------------------------
  48. BOOL GetRAInfo(CEP_RA_INFO *pRAInfo)
  49. {
  50. BOOL fResult = FALSE;
  51. HCERTSTORE hCEPStore=NULL;
  52. DWORD dwSize=0;
  53. DWORD dwIndex=0;
  54. HANDLE hThread=NULL; //no need to close
  55. HANDLE hToken=NULL;
  56. HCERTSTORE hSignStore=NULL;
  57. CERT_ENHKEY_USAGE *pKeyUsage = NULL;
  58. memset(pRAInfo, 0, sizeof(CEP_RA_INFO));
  59. // so we can get access to the local machine's private key
  60. hThread=GetCurrentThread();
  61. if(NULL != hThread)
  62. {
  63. if(OpenThreadToken(hThread,
  64. TOKEN_IMPERSONATE | TOKEN_QUERY,
  65. FALSE,
  66. &hToken))
  67. {
  68. if(hToken)
  69. {
  70. //no need to check for return here. If this failed, just go on
  71. RevertToSelf();
  72. }
  73. }
  74. }
  75. //sign RA
  76. if(!(hSignStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  77. ENCODE_TYPE,
  78. NULL,
  79. CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG,
  80. L"CEPSIGN")))
  81. goto TraceErr;
  82. if(!(pRAInfo->pRASign=CertEnumCertificatesInStore(
  83. hSignStore,
  84. NULL)))
  85. goto TraceErr;
  86. //the RA cert should have private key and enrollment agent usage
  87. dwSize=0;
  88. if(!CertGetCertificateContextProperty(
  89. pRAInfo->pRASign,
  90. CERT_KEY_PROV_INFO_PROP_ID,
  91. NULL,
  92. &dwSize) || (0==dwSize))
  93. goto InvalidArgErr;
  94. if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRASign,
  95. CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG,
  96. NULL,
  97. &(pRAInfo->hSignProv),
  98. &(pRAInfo->dwSignKeySpec),
  99. &(pRAInfo->fSignFree)))
  100. goto TraceErr;
  101. //exchange RA
  102. if(!(hCEPStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  103. ENCODE_TYPE,
  104. NULL,
  105. CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG,
  106. CEP_STORE_NAME)))
  107. goto TraceErr;
  108. if(!(pRAInfo->pRACert=CertEnumCertificatesInStore(
  109. hCEPStore,
  110. NULL)))
  111. goto TraceErr;
  112. //the RA cert should have private key and enrollment agent usage
  113. dwSize=0;
  114. if(!CertGetCertificateContextProperty(
  115. pRAInfo->pRACert,
  116. CERT_KEY_PROV_INFO_PROP_ID,
  117. NULL,
  118. &dwSize) || (0==dwSize))
  119. goto InvalidArgErr;
  120. if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRACert,
  121. CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG,
  122. NULL,
  123. &(pRAInfo->hRAProv),
  124. &(pRAInfo->dwKeySpec),
  125. &(pRAInfo->fFree)))
  126. goto TraceErr;
  127. if(!CertGetEnhancedKeyUsage(pRAInfo->pRACert,
  128. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  129. NULL,
  130. &dwSize))
  131. goto InvalidArgErr;
  132. if(NULL==(pKeyUsage=(CERT_ENHKEY_USAGE *)malloc(dwSize)))
  133. goto MemoryErr;
  134. if (!CertGetEnhancedKeyUsage(pRAInfo->pRACert,
  135. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  136. pKeyUsage,
  137. &dwSize))
  138. goto InvalidArgErr;
  139. for(dwIndex=0; dwIndex < pKeyUsage->cUsageIdentifier; dwIndex++)
  140. {
  141. if(0 == strcmp(pKeyUsage->rgpszUsageIdentifier[dwIndex], szOID_ENROLLMENT_AGENT))
  142. {
  143. fResult=TRUE;
  144. break;
  145. }
  146. }
  147. if(!fResult)
  148. goto ErrorReturn;
  149. CommonReturn:
  150. if(hCEPStore)
  151. CertCloseStore(hCEPStore, 0);
  152. if(hSignStore)
  153. CertCloseStore(hSignStore, 0);
  154. if(pKeyUsage)
  155. free(pKeyUsage);
  156. //if hToken is valid, we reverted to ourselves.
  157. if(hToken)
  158. {
  159. SetThreadToken(&hThread, hToken);
  160. CloseHandle(hToken);
  161. }
  162. return fResult;
  163. ErrorReturn:
  164. FreeRAInformation(pRAInfo);
  165. fResult=FALSE;
  166. goto CommonReturn;
  167. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  168. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  169. TRACE_ERROR(TraceErr);
  170. } */
  171. //--------------------------------------------------------------------------
  172. //
  173. // SigningCert
  174. //
  175. //--------------------------------------------------------------------------
  176. BOOL WINAPI SigningCert(PCCERT_CONTEXT pCertContext)
  177. {
  178. BOOL fSign=FALSE;
  179. PCERT_EXTENSION pExt=NULL;
  180. DWORD cbSize=0;
  181. CRYPT_BIT_BLOB *pKeyUsage=NULL;
  182. if(!pCertContext)
  183. goto CLEANUP;
  184. if(!(pExt=CertFindExtension(
  185. szOID_KEY_USAGE,
  186. pCertContext->pCertInfo->cExtension,
  187. pCertContext->pCertInfo->rgExtension)))
  188. goto CLEANUP;
  189. if(!CryptDecodeObject(ENCODE_TYPE,
  190. X509_KEY_USAGE,
  191. pExt->Value.pbData,
  192. pExt->Value.cbData,
  193. 0,
  194. NULL,
  195. &cbSize))
  196. goto CLEANUP;
  197. pKeyUsage=(CRYPT_BIT_BLOB *)malloc(cbSize);
  198. if(NULL==pKeyUsage)
  199. goto CLEANUP;
  200. if(!CryptDecodeObject(ENCODE_TYPE,
  201. X509_KEY_USAGE,
  202. pExt->Value.pbData,
  203. pExt->Value.cbData,
  204. 0,
  205. pKeyUsage,
  206. &cbSize))
  207. goto CLEANUP;
  208. if(CERT_DIGITAL_SIGNATURE_KEY_USAGE & (pKeyUsage->pbData[0]))
  209. fSign=TRUE;
  210. CLEANUP:
  211. if(pKeyUsage)
  212. free(pKeyUsage);
  213. return fSign;
  214. }
  215. //--------------------------------------------------------------------------
  216. //
  217. // GetConfigInfo
  218. //
  219. //--------------------------------------------------------------------------
  220. BOOL WINAPI GetConfigInfo(DWORD *pdwRefreshDays, BOOL *pfPassword)
  221. {
  222. DWORD cbData=0;
  223. DWORD dwData=0;
  224. DWORD dwType=0;
  225. BOOL fResult=FALSE;
  226. long dwErr=0;
  227. HKEY hKeyRefresh=NULL;
  228. HKEY hKeyPassword=NULL;
  229. if(!pdwRefreshDays || !pfPassword)
  230. goto InvalidArgErr;
  231. //default the refresh days
  232. *pdwRefreshDays=CEP_REFRESH_DAY;
  233. *pfPassword=FALSE;
  234. if(ERROR_SUCCESS == RegOpenKeyExU(
  235. HKEY_LOCAL_MACHINE,
  236. MSCEP_REFRESH_LOCATION,
  237. 0,
  238. KEY_READ,
  239. &hKeyRefresh))
  240. {
  241. cbData=sizeof(dwData);
  242. if(ERROR_SUCCESS == RegQueryValueExU(
  243. hKeyRefresh,
  244. MSCEP_KEY_REFRESH,
  245. NULL,
  246. &dwType,
  247. (BYTE *)&dwData,
  248. &cbData))
  249. {
  250. if ((dwType == REG_DWORD) ||
  251. (dwType == REG_BINARY))
  252. {
  253. *pdwRefreshDays=dwData;
  254. }
  255. }
  256. }
  257. dwType=0;
  258. dwData=0;
  259. cbData=sizeof(dwData);
  260. //we have to have the knowledge of the password policy
  261. if(ERROR_SUCCESS != (dwErr = RegOpenKeyExU(
  262. HKEY_LOCAL_MACHINE,
  263. MSCEP_PASSWORD_LOCATION,
  264. 0,
  265. KEY_READ,
  266. &hKeyPassword)))
  267. goto RegErr;
  268. if(ERROR_SUCCESS != (dwErr = RegQueryValueExU(
  269. hKeyPassword,
  270. MSCEP_KEY_PASSWORD,
  271. NULL,
  272. &dwType,
  273. (BYTE *)&dwData,
  274. &cbData)))
  275. goto RegErr;
  276. if ((dwType != REG_DWORD) &&
  277. (dwType != REG_BINARY))
  278. goto RegErr;
  279. if(0 == dwData)
  280. *pfPassword=FALSE;
  281. else
  282. *pfPassword=TRUE;
  283. fResult=TRUE;
  284. CommonReturn:
  285. if(hKeyRefresh)
  286. RegCloseKey(hKeyRefresh);
  287. if(hKeyPassword)
  288. RegCloseKey(hKeyPassword);
  289. return fResult;
  290. ErrorReturn:
  291. if(pdwRefreshDays)
  292. *pdwRefreshDays=0;
  293. if(pfPassword)
  294. *pfPassword=FALSE;
  295. fResult=FALSE;
  296. goto CommonReturn;
  297. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  298. SET_ERROR_VAR(RegErr, dwErr);
  299. }
  300. //--------------------------------------------------------------------------
  301. //
  302. // GetRAInfo
  303. //
  304. // We need to have two RA cert: One for signature cert (also the enrollment
  305. // agent) and one for the key encipherment.
  306. //--------------------------------------------------------------------------
  307. BOOL GetRAInfo(CEP_RA_INFO *pRAInfo)
  308. {
  309. BOOL fResult = FALSE;
  310. BOOL fFound = FALSE;
  311. DWORD dwSize=0;
  312. DWORD dwIndex=0;
  313. HANDLE hThread=NULL; //no need to close
  314. PCCERT_CONTEXT pPreCert=NULL;
  315. HCERTSTORE hCEPStore=NULL;
  316. CERT_ENHKEY_USAGE *pKeyUsage = NULL;
  317. PCCERT_CONTEXT pCurCert=NULL;
  318. HANDLE hToken=NULL;
  319. memset(pRAInfo, 0, sizeof(CEP_RA_INFO));
  320. if(!GetConfigInfo(&(pRAInfo->dwRefreshDays), &(pRAInfo->fPassword)))
  321. goto TraceErr;
  322. // so we can get access to the local machine's private key
  323. hThread=GetCurrentThread();
  324. if(NULL != hThread)
  325. {
  326. if(OpenThreadToken(hThread,
  327. TOKEN_IMPERSONATE | TOKEN_QUERY,
  328. FALSE,
  329. &hToken))
  330. {
  331. if(hToken)
  332. {
  333. //no need to check for return here. If this failed, just go on
  334. RevertToSelf();
  335. }
  336. }
  337. }
  338. if(!(hCEPStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  339. ENCODE_TYPE,
  340. NULL,
  341. CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG,
  342. CEP_STORE_NAME)))
  343. goto TraceErr;
  344. while(pCurCert=CertEnumCertificatesInStore(hCEPStore,
  345. pPreCert))
  346. {
  347. //has to have a private key
  348. dwSize=0;
  349. if(!CertGetCertificateContextProperty(
  350. pCurCert,
  351. CERT_KEY_PROV_INFO_PROP_ID,
  352. NULL,
  353. &dwSize) || (0==dwSize))
  354. goto InvalidArgErr;
  355. //decide based on the key usage
  356. if(SigningCert(pCurCert))
  357. {
  358. //one signing RA Only
  359. if(pRAInfo->pRASign)
  360. goto InvalidArgErr;
  361. if(!(pRAInfo->pRASign=CertDuplicateCertificateContext(pCurCert)))
  362. goto TraceErr;
  363. if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRASign,
  364. CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG,
  365. NULL,
  366. &(pRAInfo->hSignProv),
  367. &(pRAInfo->dwSignKeySpec),
  368. &(pRAInfo->fSignFree)))
  369. goto TraceErr;
  370. //has to have the enrollment agent eku
  371. dwSize=0;
  372. if(!CertGetEnhancedKeyUsage(pCurCert,
  373. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  374. NULL,
  375. &dwSize))
  376. goto InvalidArgErr;
  377. if(NULL==(pKeyUsage=(CERT_ENHKEY_USAGE *)malloc(dwSize)))
  378. goto MemoryErr;
  379. if (!CertGetEnhancedKeyUsage(pCurCert,
  380. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  381. pKeyUsage,
  382. &dwSize))
  383. goto InvalidArgErr;
  384. fFound=FALSE;
  385. for(dwIndex=0; dwIndex < pKeyUsage->cUsageIdentifier; dwIndex++)
  386. {
  387. if(0 == strcmp(pKeyUsage->rgpszUsageIdentifier[dwIndex], szOID_ENROLLMENT_AGENT))
  388. {
  389. fFound=TRUE;
  390. break;
  391. }
  392. }
  393. if(!fFound)
  394. goto InvalidArgErr;
  395. }
  396. else
  397. {
  398. //one encryption RA only
  399. if(pRAInfo->pRACert)
  400. goto InvalidArgErr;
  401. if(!(pRAInfo->pRACert=CertDuplicateCertificateContext(pCurCert)))
  402. goto TraceErr;
  403. if(!CryptAcquireCertificatePrivateKey(pRAInfo->pRACert,
  404. CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG,
  405. NULL,
  406. &(pRAInfo->hRAProv),
  407. &(pRAInfo->dwKeySpec),
  408. &(pRAInfo->fFree)))
  409. goto TraceErr;
  410. }
  411. if(pKeyUsage)
  412. {
  413. free(pKeyUsage);
  414. pKeyUsage=NULL;
  415. }
  416. pPreCert=pCurCert;
  417. }
  418. //we have to have both RA certs
  419. if((NULL == pRAInfo->pRACert) ||
  420. (NULL == pRAInfo->pRASign))
  421. goto InvalidArgErr;
  422. fResult=TRUE;
  423. CommonReturn:
  424. if(hCEPStore)
  425. CertCloseStore(hCEPStore, 0);
  426. if(pKeyUsage)
  427. free(pKeyUsage);
  428. //if hToken is valid, we reverted to ourselves.
  429. if(hToken)
  430. {
  431. SetThreadToken(&hThread, hToken);
  432. CloseHandle(hToken);
  433. }
  434. if(pCurCert)
  435. CertFreeCertificateContext(pCurCert);
  436. return fResult;
  437. ErrorReturn:
  438. FreeRAInformation(pRAInfo);
  439. fResult=FALSE;
  440. goto CommonReturn;
  441. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  442. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  443. TRACE_ERROR(TraceErr);
  444. }
  445. //--------------------------------------------------------------------------
  446. //
  447. // OperationGetPKI
  448. //
  449. //--------------------------------------------------------------------------
  450. BOOL OperationGetPKI( CEP_RA_INFO *pRAInfo,
  451. CEP_CA_INFO *pCAInfo,
  452. LPSTR szMsg,
  453. BYTE **ppbData,
  454. DWORD *pcbData)
  455. {
  456. BOOL fResult = FALSE;
  457. CEP_MESSAGE_INFO MsgInfo;
  458. DWORD cbContent=0;
  459. DWORD cbEnvelop=1;
  460. BYTE bFoo=0;
  461. BYTE *pbContent=NULL;
  462. BYTE *pbEnvelop=&bFoo;
  463. memset(&MsgInfo, 0, sizeof(CEP_MESSAGE_INFO));
  464. if(!GetReturnInfoAndContent(pRAInfo, pCAInfo, szMsg, &pbContent, &cbContent, &MsgInfo))
  465. goto TraceErr;
  466. //envelop the data
  467. if(MESSAGE_STATUS_SUCCESS == MsgInfo.dwStatus)
  468. {
  469. if(!EnvelopData(MsgInfo.pSigningCert, pbContent, cbContent,
  470. &pbEnvelop, &cbEnvelop))
  471. {
  472. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_ENCRYPT, 1, g_pwszComputerName);
  473. goto TraceErr;
  474. }
  475. }
  476. //sign the data with authenticated attributes
  477. //when the dwStatus is not SUCCESS, the pbEnvelop is NULL and cbEnvelop is 0.
  478. if(!SignData(&MsgInfo, pRAInfo, pbEnvelop, cbEnvelop, ppbData, pcbData))
  479. {
  480. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_SIGN, 1, g_pwszComputerName);
  481. goto TraceErr;
  482. }
  483. fResult = TRUE;
  484. CommonReturn:
  485. if(pbContent)
  486. free(pbContent);
  487. if(&bFoo != pbEnvelop)
  488. free(pbEnvelop);
  489. FreeMessageInfo(&MsgInfo);
  490. return fResult;
  491. ErrorReturn:
  492. fResult=FALSE;
  493. goto CommonReturn;
  494. TRACE_ERROR(TraceErr);
  495. }
  496. //--------------------------------------------------------------------------
  497. //
  498. // SignData
  499. //
  500. // the messageType is always response and the senderNonce should be generated
  501. // in case the pending and failure, pbEnvelop will be NULL.
  502. //
  503. // In the initial GetContentFromPKCS7, we retrive MessageType, TransactionID,
  504. // RecipientNonce, signing Cert serial number.
  505. //
  506. // In the process, we get the dwStatus and dwErrorInfo when applicable.
  507. ////--------------------------------------------------------------------------
  508. BOOL SignData(CEP_MESSAGE_INFO *pMsgInfo,
  509. CEP_RA_INFO *pRAInfo,
  510. BYTE *pbEnvelop,
  511. DWORD cbEnvelop,
  512. BYTE **ppbData,
  513. DWORD *pcbData)
  514. {
  515. BOOL fResult = FALSE;
  516. CMSG_SIGNER_ENCODE_INFO SignerInfo;
  517. CMSG_SIGNED_ENCODE_INFO SignEncodedInfo;
  518. CERT_BLOB CertBlob;
  519. BOOL fProvFree=FALSE;
  520. PCCRYPT_OID_INFO pOIDInfo=NULL;
  521. ALG_ID AlgValue=CALG_MD5;
  522. DWORD cAttr=0;
  523. CRYPT_ATTR_BLOB rgAttrBlob[CEP_RESPONSE_AUTH_ATTR_COUNT];
  524. DWORD dwIndex=0;
  525. HCRYPTMSG hMsg=NULL;
  526. CRYPT_ATTRIBUTE rgAttr[CEP_RESPONSE_AUTH_ATTR_COUNT];
  527. if(!pMsgInfo || !pRAInfo || !ppbData || !pcbData)
  528. goto InvalidArgErr;
  529. *ppbData=NULL;
  530. *pcbData=0;
  531. pMsgInfo->dwMessageType=MESSAGE_TYPE_CERT_RESPONSE;
  532. if(!GenerateSenderNonce(&(pMsgInfo->SenderNonce)))
  533. goto TraceErr;
  534. memset(&SignerInfo, 0, sizeof(SignerInfo));
  535. memset(&SignEncodedInfo, 0, sizeof(SignEncodedInfo));
  536. SignEncodedInfo.cbSize=sizeof(SignEncodedInfo);
  537. SignEncodedInfo.cSigners=1;
  538. SignEncodedInfo.rgSigners=&SignerInfo,
  539. /* SignEncodedInfo.cCertEncoded=1;
  540. SignEncodedInfo.rgCertEncoded=&CertBlob; */
  541. SignEncodedInfo.cCertEncoded=0;
  542. SignEncodedInfo.rgCertEncoded=NULL;
  543. SignEncodedInfo.cCrlEncoded=0;
  544. SignEncodedInfo.rgCrlEncoded=NULL;
  545. CertBlob.cbData=pRAInfo->pRASign->cbCertEncoded;
  546. CertBlob.pbData=pRAInfo->pRASign->pbCertEncoded;
  547. SignerInfo.cbSize=sizeof(SignerInfo);
  548. SignerInfo.pCertInfo=pRAInfo->pRASign->pCertInfo;
  549. //specify AlgID
  550. if(pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
  551. &AlgValue,
  552. CRYPT_HASH_ALG_OID_GROUP_ID))
  553. SignerInfo.HashAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID);
  554. else
  555. SignerInfo.HashAlgorithm.pszObjId=szOID_RSA_MD5;
  556. //get the private key
  557. SignerInfo.hCryptProv=pRAInfo->hSignProv;
  558. SignerInfo.dwKeySpec=pRAInfo->dwSignKeySpec;
  559. //get the autheticated attributes
  560. //together we should have 6 attributes: TransactionID, MessageType, PkiStatus,
  561. //ErrorInfo, senderNonce, and recipientNonce
  562. memset(rgAttr, 0, CEP_RESPONSE_AUTH_ATTR_COUNT * sizeof(CRYPT_ATTRIBUTE));
  563. memset(rgAttrBlob, 0, CEP_RESPONSE_AUTH_ATTR_COUNT * sizeof(CRYPT_ATTR_BLOB));
  564. for(dwIndex=0; dwIndex<CEP_RESPONSE_AUTH_ATTR_COUNT; dwIndex++)
  565. {
  566. rgAttr[dwIndex].cValue=1;
  567. rgAttr[dwIndex].rgValue=&(rgAttrBlob[dwIndex]);
  568. }
  569. cAttr=0;
  570. //TransactionID
  571. rgAttr[cAttr].pszObjId=szOIDVerisign_TransactionID;
  572. //transactionID internally are stored as a string
  573. pMsgInfo->TransactionID.cbData=strlen((LPSTR)(pMsgInfo->TransactionID.pbData));
  574. if(!CEPAllocAndEncodeName(CERT_RDN_PRINTABLE_STRING,
  575. pMsgInfo->TransactionID.pbData,
  576. pMsgInfo->TransactionID.cbData,
  577. &(rgAttr[cAttr].rgValue[0].pbData),
  578. &(rgAttr[cAttr].rgValue[0].cbData)))
  579. goto TraceErr;
  580. cAttr++;
  581. //MessageType
  582. rgAttr[cAttr].pszObjId=szOIDVerisign_MessageType;
  583. if(!CEPAllocAndEncodeDword(CERT_RDN_PRINTABLE_STRING,
  584. pMsgInfo->dwMessageType,
  585. &(rgAttr[cAttr].rgValue[0].pbData),
  586. &(rgAttr[cAttr].rgValue[0].cbData)))
  587. goto TraceErr;
  588. cAttr++;
  589. //Status
  590. rgAttr[cAttr].pszObjId=szOIDVerisign_PkiStatus;
  591. if(!CEPAllocAndEncodeDword(CERT_RDN_PRINTABLE_STRING,
  592. pMsgInfo->dwStatus,
  593. &(rgAttr[cAttr].rgValue[0].pbData),
  594. &(rgAttr[cAttr].rgValue[0].cbData)))
  595. goto TraceErr;
  596. cAttr++;
  597. //ErrorInfo only if the error case
  598. if(MESSAGE_STATUS_FAILURE == pMsgInfo->dwStatus)
  599. {
  600. rgAttr[cAttr].pszObjId=szOIDVerisign_FailInfo;
  601. if(!CEPAllocAndEncodeDword(CERT_RDN_PRINTABLE_STRING,
  602. pMsgInfo->dwErrorInfo,
  603. &(rgAttr[cAttr].rgValue[0].pbData),
  604. &(rgAttr[cAttr].rgValue[0].cbData)))
  605. goto TraceErr;
  606. cAttr++;
  607. }
  608. //senderNonce
  609. rgAttr[cAttr].pszObjId=szOIDVerisign_SenderNonce;
  610. if(!CEPAllocAndEncodeName(CERT_RDN_OCTET_STRING,
  611. pMsgInfo->SenderNonce.pbData,
  612. pMsgInfo->SenderNonce.cbData,
  613. &(rgAttr[cAttr].rgValue[0].pbData),
  614. &(rgAttr[cAttr].rgValue[0].cbData)))
  615. goto TraceErr;
  616. cAttr++;
  617. //recipientNonce
  618. rgAttr[cAttr].pszObjId=szOIDVerisign_RecipientNonce;
  619. if(!CEPAllocAndEncodeName(CERT_RDN_OCTET_STRING,
  620. pMsgInfo->RecipientNonce.pbData,
  621. pMsgInfo->RecipientNonce.cbData,
  622. &(rgAttr[cAttr].rgValue[0].pbData),
  623. &(rgAttr[cAttr].rgValue[0].cbData)))
  624. goto TraceErr;
  625. cAttr++;
  626. SignerInfo.cAuthAttr=cAttr;
  627. SignerInfo.rgAuthAttr=rgAttr;
  628. //message encoding
  629. if(NULL==(hMsg=CryptMsgOpenToEncode(ENCODE_TYPE,
  630. 0,
  631. CMSG_SIGNED,
  632. &SignEncodedInfo,
  633. NULL, //we are encoding as CMSG_DATA(7.1)
  634. NULL)))
  635. goto TraceErr;
  636. if(!CryptMsgUpdate(hMsg,
  637. pbEnvelop,
  638. cbEnvelop,
  639. TRUE))
  640. goto TraceErr;
  641. if(!CryptMsgGetParam(hMsg,
  642. CMSG_CONTENT_PARAM,
  643. 0,
  644. NULL,
  645. pcbData))
  646. goto TraceErr;
  647. *ppbData=(BYTE *)malloc(*pcbData);
  648. if(NULL==(*ppbData))
  649. goto MemoryErr;
  650. if(!CryptMsgGetParam(hMsg,
  651. CMSG_CONTENT_PARAM,
  652. 0,
  653. *ppbData,
  654. pcbData))
  655. goto TraceErr;
  656. fResult = TRUE;
  657. CommonReturn:
  658. for(dwIndex=0; dwIndex < cAttr; dwIndex ++)
  659. {
  660. if(rgAttrBlob[dwIndex].pbData)
  661. free(rgAttrBlob[dwIndex].pbData);
  662. }
  663. if(hMsg)
  664. CryptMsgClose(hMsg);
  665. return fResult;
  666. ErrorReturn:
  667. if(ppbData)
  668. {
  669. if(*ppbData)
  670. {
  671. free(*ppbData);
  672. *ppbData=NULL;
  673. }
  674. }
  675. if(pcbData)
  676. *pcbData=0;
  677. fResult=FALSE;
  678. goto CommonReturn;
  679. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  680. TRACE_ERROR(TraceErr);
  681. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  682. }
  683. //--------------------------------------------------------------------------
  684. //
  685. // CEPAllocAndEncodeDword
  686. //
  687. // PreCondition: ppbEncoded and pcbEncoded should not be NULL.
  688. // The dwData is no more than 11
  689. //--------------------------------------------------------------------------
  690. BOOL CEPAllocAndEncodeDword(DWORD dwValueType,
  691. DWORD dwData,
  692. BYTE **ppbEncoded,
  693. DWORD *pcbEncoded)
  694. {
  695. BOOL fResult = FALSE;
  696. CHAR szString[12];
  697. BYTE *pbData=NULL;
  698. DWORD cbData=0;
  699. _ltoa(dwData, szString, 10);
  700. pbData=(BYTE *)szString;
  701. cbData=strlen(szString);
  702. return CEPAllocAndEncodeName(dwValueType, pbData, cbData, ppbEncoded, pcbEncoded);
  703. }
  704. //--------------------------------------------------------------------------
  705. //
  706. // CEPAllocAndEncodeName
  707. //
  708. // PreCondition: ppbEncoded and pcbEncoded should not be NULL.
  709. //--------------------------------------------------------------------------
  710. BOOL CEPAllocAndEncodeName(DWORD dwValueType,
  711. BYTE *pbData,
  712. DWORD cbData,
  713. BYTE **ppbEncoded,
  714. DWORD *pcbEncoded)
  715. {
  716. CERT_NAME_VALUE CertName;
  717. *ppbEncoded=NULL;
  718. *pcbEncoded=0;
  719. CertName.dwValueType=dwValueType;
  720. CertName.Value.pbData=pbData;
  721. CertName.Value.cbData=cbData;
  722. return CEPAllocAndEncode(X509_ANY_STRING,
  723. &CertName,
  724. ppbEncoded,
  725. pcbEncoded);
  726. }
  727. //--------------------------------------------------------------------------
  728. //
  729. // GenerateSenderNonce
  730. //
  731. // We use GUID to generate a random 16 byte number
  732. //
  733. //--------------------------------------------------------------------------
  734. BOOL GenerateSenderNonce(CRYPT_INTEGER_BLOB *pBlob)
  735. {
  736. BOOL fResult = FALSE;
  737. GUID guid;
  738. BYTE *pData=NULL;
  739. UuidCreate(&guid);
  740. pBlob->cbData=sizeof(guid.Data1) + sizeof(guid.Data2) +
  741. sizeof(guid.Data3) + sizeof(guid.Data4);
  742. pBlob->pbData=(BYTE *)malloc(pBlob->cbData);
  743. if(NULL==(pBlob->pbData))
  744. goto MemoryErr;
  745. pData=pBlob->pbData;
  746. memcpy(pData, &(guid.Data1), sizeof(guid.Data1));
  747. pData += sizeof(guid.Data1);
  748. memcpy(pData, &(guid.Data2), sizeof(guid.Data2));
  749. pData += sizeof(guid.Data2);
  750. memcpy(pData, &(guid.Data3), sizeof(guid.Data3));
  751. pData += sizeof(guid.Data3);
  752. memcpy(pData, &(guid.Data4), sizeof(guid.Data4));
  753. fResult = TRUE;
  754. CommonReturn:
  755. return fResult;
  756. ErrorReturn:
  757. fResult=FALSE;
  758. goto CommonReturn;
  759. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  760. }
  761. //--------------------------------------------------------------------------
  762. //
  763. // EnvelopData
  764. //
  765. // In the initial GetContentFromPKCS7, we retrieve pSigningCert for
  766. // GetCertInitial, CertReq, and GetCert request.
  767. //
  768. // In the process,we retrieve pSigningCert for GetCRL request.
  769. //--------------------------------------------------------------------------
  770. BOOL EnvelopData(PCCERT_CONTEXT pSigningCert,
  771. BYTE *pbContent,
  772. DWORD cbContent,
  773. BYTE **ppbEnvelop,
  774. DWORD *pcbEnvelop)
  775. {
  776. BOOL fResult = FALSE;
  777. CMSG_ENVELOPED_ENCODE_INFO EnvInfo;
  778. HCRYPTMSG hMsg=NULL;
  779. if(!pSigningCert || !pbContent || !ppbEnvelop || !pcbEnvelop)
  780. goto InvalidArgErr;
  781. *ppbEnvelop=NULL;
  782. *pcbEnvelop=0;
  783. memset(&EnvInfo, 0, sizeof(CMSG_ENVELOPED_ENCODE_INFO));
  784. EnvInfo.cbSize=sizeof(CMSG_ENVELOPED_ENCODE_INFO);
  785. EnvInfo.hCryptProv=NULL;
  786. EnvInfo.ContentEncryptionAlgorithm.pszObjId=szOID_OIWSEC_desCBC;
  787. EnvInfo.pvEncryptionAuxInfo=NULL;
  788. EnvInfo.cRecipients=1;
  789. EnvInfo.rgpRecipients=(PCERT_INFO *)(&(pSigningCert->pCertInfo));
  790. if(NULL==(hMsg=CryptMsgOpenToEncode(ENCODE_TYPE,
  791. 0,
  792. CMSG_ENVELOPED,
  793. &EnvInfo,
  794. NULL, //we are encoding as CMSG_DATA(7.1)
  795. NULL)))
  796. goto TraceErr;
  797. if(!CryptMsgUpdate(hMsg,
  798. pbContent,
  799. cbContent,
  800. TRUE))
  801. goto TraceErr;
  802. if(!CryptMsgGetParam(hMsg,
  803. CMSG_CONTENT_PARAM,
  804. 0,
  805. NULL,
  806. pcbEnvelop))
  807. goto TraceErr;
  808. *ppbEnvelop=(BYTE *)malloc(*pcbEnvelop);
  809. if(NULL==(*ppbEnvelop))
  810. goto MemoryErr;
  811. if(!CryptMsgGetParam(hMsg,
  812. CMSG_CONTENT_PARAM,
  813. 0,
  814. *ppbEnvelop,
  815. pcbEnvelop))
  816. goto TraceErr;
  817. fResult = TRUE;
  818. CommonReturn:
  819. if(hMsg)
  820. CryptMsgClose(hMsg);
  821. return fResult;
  822. ErrorReturn:
  823. if(ppbEnvelop)
  824. {
  825. if(*ppbEnvelop)
  826. {
  827. free(*ppbEnvelop);
  828. *ppbEnvelop=NULL;
  829. }
  830. }
  831. if(pcbEnvelop)
  832. *pcbEnvelop=0;
  833. fResult=FALSE;
  834. goto CommonReturn;
  835. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  836. TRACE_ERROR(TraceErr);
  837. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  838. }
  839. //--------------------------------------------------------------------------
  840. //
  841. // DecodeCertW
  842. //
  843. //--------------------------------------------------------------------------
  844. HRESULT
  845. DecodeCertW(
  846. IN void const *pchIn,
  847. IN DWORD cchIn,
  848. IN DWORD Flags,
  849. OUT BYTE **ppbOut,
  850. OUT DWORD *pcbOut)
  851. {
  852. HRESULT hr;
  853. BYTE *pbOut = NULL;
  854. DWORD cbOut;
  855. BOOL fRet;
  856. //init
  857. *ppbOut = NULL;
  858. *pcbOut = 0;
  859. while (TRUE)
  860. {
  861. fRet = CryptStringToBinaryW((LPCWSTR)pchIn, cchIn, Flags, pbOut, &cbOut, NULL, NULL);
  862. if (!fRet)
  863. {
  864. hr = GetLastError();
  865. goto error;
  866. }
  867. if (NULL != pbOut)
  868. {
  869. break; //done
  870. }
  871. pbOut = (BYTE*)LocalAlloc(LMEM_FIXED, cbOut);
  872. if (NULL == pbOut)
  873. {
  874. hr = E_OUTOFMEMORY;
  875. goto error;
  876. }
  877. }
  878. *ppbOut = pbOut;
  879. pbOut = NULL;
  880. *pcbOut = cbOut;
  881. hr = S_OK;
  882. error:
  883. if (NULL != pbOut)
  884. {
  885. LocalFree(pbOut);
  886. }
  887. return hr;
  888. }
  889. //--------------------------------------------------------------------------
  890. //
  891. // GetReturnInfoAndContent
  892. //
  893. //--------------------------------------------------------------------------
  894. BOOL GetReturnInfoAndContent(CEP_RA_INFO *pRAInfo,
  895. CEP_CA_INFO *pCAInfo,
  896. LPSTR szMsg,
  897. BYTE **ppbData,
  898. DWORD *pcbData,
  899. CEP_MESSAGE_INFO *pMsgInfo)
  900. {
  901. BOOL fResult = FALSE;
  902. DWORD cbBase64Decoded=0;
  903. DWORD cbReqEnv=0;
  904. DWORD cbReqDecrypt=0;
  905. DWORD cbSize=0;
  906. HRESULT hr=E_FAIL;
  907. BYTE *pbBase64Decoded=NULL;
  908. BYTE *pbReqEnv=NULL;
  909. BYTE *pbReqDecrypt=NULL;
  910. WCHAR wszBuffer[INTERNET_MAX_PATH_LENGTH * 2 +1];
  911. LPWSTR pwszMsg=NULL;
  912. LPWSTR pwszBuffer=NULL;
  913. //convert sz to wsz
  914. pwszMsg=MkWStr(szMsg);
  915. if(NULL==pwszMsg)
  916. goto MemoryErr;
  917. //we need to get rid of the escape characters
  918. if(S_OK != (hr=CoInternetParseUrl(pwszMsg,
  919. PARSE_UNESCAPE,
  920. 0,
  921. wszBuffer,
  922. INTERNET_MAX_PATH_LENGTH*2,
  923. &cbSize,
  924. 0)))
  925. {
  926. //S_FALSE means that the buffer is too small
  927. if(S_FALSE != hr)
  928. {
  929. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_CONVERT, 1, g_pwszComputerName);
  930. goto TraceErr;
  931. }
  932. if(0==cbSize)
  933. {
  934. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_CONVERT, 1, g_pwszComputerName);
  935. goto TraceErr;
  936. }
  937. //allocate the buffer
  938. pwszBuffer=(LPWSTR)malloc(cbSize * sizeof(WCHAR));
  939. if(NULL==pwszBuffer)
  940. goto MemoryErr;
  941. *pwszBuffer=L'\0';
  942. if(S_OK != (hr = CoInternetParseUrl(pwszMsg,
  943. PARSE_UNESCAPE,
  944. 0,
  945. pwszBuffer,
  946. cbSize,
  947. &cbSize,
  948. 0)))
  949. {
  950. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_CONVERT, 1, g_pwszComputerName);
  951. goto TraceErr;
  952. }
  953. }
  954. if(S_OK != (hr = DecodeCertW(
  955. pwszBuffer ? pwszBuffer : wszBuffer,
  956. pwszBuffer ? wcslen(pwszBuffer) : wcslen(wszBuffer),
  957. CRYPT_STRING_BASE64_ANY, //DECF_BASE64_ANY,
  958. &pbBase64Decoded,
  959. &cbBase64Decoded)))
  960. {
  961. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_TO_DECODE, 1, g_pwszComputerName);
  962. goto FailureStatusReturn;
  963. }
  964. //get the message type, transaction ID, recepientNonce, serial number in the
  965. //signer_info of the most outer PKCS#7 and inner content
  966. if(!GetContentFromPKCS7(pbBase64Decoded,
  967. cbBase64Decoded,
  968. &pbReqEnv,
  969. &cbReqEnv,
  970. pMsgInfo))
  971. {
  972. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_RETRIEVE_INFO, 1, g_pwszComputerName);
  973. goto FailureStatusReturn;
  974. }
  975. //decrypt the inner content
  976. if(!DecryptMsg(pRAInfo, pbReqEnv, cbReqEnv, &pbReqDecrypt, &cbReqDecrypt))
  977. {
  978. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_DECRYPT_INNER, 1, g_pwszComputerName);
  979. goto FailureStatusReturn;
  980. }
  981. //get the return inner content based on the message type
  982. switch(pMsgInfo->dwMessageType)
  983. {
  984. case MESSAGE_TYPE_CERT_REQUEST:
  985. //we use the signing RA cert as the enrollment agent
  986. if(!ProcessCertRequest( pRAInfo->dwRefreshDays,
  987. pRAInfo->fPassword,
  988. pRAInfo->pRACert,
  989. pRAInfo->pRASign,
  990. pCAInfo,
  991. pbReqDecrypt,
  992. cbReqDecrypt,
  993. ppbData,
  994. pcbData,
  995. pMsgInfo))
  996. {
  997. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_CERT_REQ, 1, g_pwszComputerName);
  998. goto TraceErr;
  999. }
  1000. break;
  1001. case MESSAGE_TYPE_GET_CERT_INITIAL:
  1002. if(!ProcessCertInitial(pRAInfo->dwRefreshDays, pCAInfo, pbReqDecrypt,
  1003. cbReqDecrypt, ppbData, pcbData,
  1004. pMsgInfo))
  1005. {
  1006. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_GET_CERT_INITIAL, 1, g_pwszComputerName);
  1007. goto TraceErr;
  1008. }
  1009. break;
  1010. case MESSAGE_TYPE_GET_CERT:
  1011. if(!ProcessGetCert(pCAInfo, pbReqDecrypt,
  1012. cbReqDecrypt, ppbData, pcbData,
  1013. pMsgInfo))
  1014. {
  1015. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_GET_CERT, 1, g_pwszComputerName);
  1016. goto TraceErr;
  1017. }
  1018. break;
  1019. case MESSAGE_TYPE_GET_CRL:
  1020. if(!ProcessGetCRL(pCAInfo, pbReqDecrypt,
  1021. cbReqDecrypt, ppbData, pcbData,
  1022. pMsgInfo))
  1023. {
  1024. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_GET_CRL, 1, g_pwszComputerName);
  1025. goto TraceErr;
  1026. }
  1027. break;
  1028. default:
  1029. LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_BAD_MESSAGE_TYPE, 1, g_pwszComputerName);
  1030. goto InvalidArgErr;
  1031. break;
  1032. }
  1033. fResult = TRUE;
  1034. CommonReturn:
  1035. if(pwszBuffer)
  1036. free(pwszBuffer);
  1037. if(pwszMsg)
  1038. FreeWStr(pwszMsg);
  1039. //memory from certcli.dll. Has to be freed by LocalFree()
  1040. if(pbBase64Decoded)
  1041. LocalFree(pbBase64Decoded);
  1042. if(pbReqEnv)
  1043. free(pbReqEnv);
  1044. if(pbReqDecrypt)
  1045. free(pbReqDecrypt);
  1046. return fResult;
  1047. FailureStatusReturn:
  1048. //we set the error status for the return message
  1049. //and consider this http transation a success
  1050. pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE;
  1051. pMsgInfo->dwErrorInfo=MESSAGE_FAILURE_BAD_MESSAGE_CHECK;
  1052. *ppbData=NULL;
  1053. *pcbData=0;
  1054. fResult=TRUE;
  1055. goto CommonReturn;
  1056. ErrorReturn:
  1057. fResult=FALSE;
  1058. goto CommonReturn;
  1059. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1060. TRACE_ERROR(TraceErr);
  1061. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1062. }
  1063. //--------------------------------------------------------------------------
  1064. //
  1065. // RetrieveContextFromSerialNumber
  1066. //
  1067. //
  1068. //--------------------------------------------------------------------------
  1069. BOOL WINAPI RetrieveContextFromSerialNumber(CEP_CA_INFO *pCAInfo,
  1070. CERT_BLOB *pSerialNumber,
  1071. PCCERT_CONTEXT *ppCertContext)
  1072. {
  1073. BOOL fResult = FALSE;
  1074. DWORD cb=0;
  1075. long dwDisposition=0;
  1076. HRESULT hr=E_FAIL;
  1077. DWORD cbCert=0;
  1078. BYTE *pbCert=NULL;
  1079. LPWSTR pwsz=NULL;
  1080. BSTR bstrCert=NULL;
  1081. LPWSTR pwszNewConfig=NULL;
  1082. BSTR bstrNewConfig=NULL;
  1083. if(S_OK != (hr=MultiByteIntegerToWszBuf(
  1084. FALSE,
  1085. pSerialNumber->cbData,
  1086. pSerialNumber->pbData,
  1087. &cb,
  1088. NULL)))
  1089. goto SetHrErr;
  1090. pwsz=(LPWSTR)malloc(cb);
  1091. if(NULL==pwsz)
  1092. goto MemoryErr;
  1093. if(S_OK != (hr=MultiByteIntegerToWszBuf(
  1094. FALSE,
  1095. pSerialNumber->cbData,
  1096. pSerialNumber->pbData,
  1097. &cb,
  1098. pwsz)))
  1099. goto SetHrErr;
  1100. //contatenate the serialNumber with the config string
  1101. pwszNewConfig=(LPWSTR)malloc(sizeof(WCHAR) *
  1102. (wcslen(pCAInfo->bstrCAConfig)+wcslen(pwsz)+wcslen(L"\\")+1));
  1103. if(NULL==pwszNewConfig)
  1104. goto MemoryErr;
  1105. //the config string to retrieve the cert based on the
  1106. //serialNumber is configString\SerialNumber
  1107. //
  1108. wcscpy(pwszNewConfig, pCAInfo->bstrCAConfig);
  1109. wcscat(pwszNewConfig, L"\\");
  1110. wcscat(pwszNewConfig, pwsz);
  1111. bstrNewConfig=SysAllocString(pwszNewConfig);
  1112. if(NULL==bstrNewConfig)
  1113. goto MemoryErr;
  1114. if(S_OK != (hr=pCAInfo->pICertRequest->RetrievePending(0,
  1115. bstrNewConfig,
  1116. &dwDisposition)))
  1117. goto SetHrErr;
  1118. if(S_OK != (hr= pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY,
  1119. &bstrCert)))
  1120. goto SetHrErr;
  1121. cbCert = (DWORD)SysStringByteLen(bstrCert);
  1122. pbCert = (BYTE *)bstrCert;
  1123. if(!(*ppCertContext=CertCreateCertificateContext(ENCODE_TYPE,
  1124. pbCert,
  1125. cbCert)))
  1126. goto TraceErr;
  1127. fResult = TRUE;
  1128. CommonReturn:
  1129. if(pwsz)
  1130. free(pwsz);
  1131. if(bstrCert)
  1132. SysFreeString(bstrCert);
  1133. if(pwszNewConfig)
  1134. free(pwszNewConfig);
  1135. if(bstrNewConfig)
  1136. SysFreeString(bstrNewConfig);
  1137. return fResult;
  1138. ErrorReturn:
  1139. fResult=FALSE;
  1140. goto CommonReturn;
  1141. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1142. SET_ERROR_VAR(SetHrErr, hr);
  1143. TRACE_ERROR(TraceErr);
  1144. }
  1145. //--------------------------------------------------------------------------
  1146. //
  1147. // ProcessGetCRL
  1148. //
  1149. //
  1150. //--------------------------------------------------------------------------
  1151. BOOL WINAPI ProcessGetCRL(CEP_CA_INFO *pCAInfo,
  1152. BYTE *pbRequest,
  1153. DWORD cbRequest,
  1154. BYTE **ppbData,
  1155. DWORD *pcbData,
  1156. CEP_MESSAGE_INFO *pMsgInfo)
  1157. {
  1158. BOOL fResult = FALSE;
  1159. DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  1160. DWORD cbUrlArray=0;
  1161. DWORD dwIndex=0;
  1162. PCCERT_CONTEXT pCertContext=NULL;
  1163. PCCRL_CONTEXT pCRLContext=NULL;
  1164. PCRYPT_URL_ARRAY pUrlArray = NULL;
  1165. if(!pCAInfo || !ppbData || !pcbData || !pMsgInfo)
  1166. goto InvalidArgErr;
  1167. *ppbData=NULL;
  1168. *pcbData=0;
  1169. //retrieve the cert context from the serialNumber
  1170. //protected by the critical Section since it uses ICertRequest interface
  1171. if(!RetrieveContextFromSerialNumber(pCAInfo, &(pMsgInfo->SerialNumber), &pCertContext))
  1172. {
  1173. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_GET_CERT_FROM_NUMBER, 1, g_pwszComputerName);
  1174. goto FailureStatusReturn;
  1175. }
  1176. if(!CryptGetObjectUrl(
  1177. URL_OID_CERTIFICATE_CRL_DIST_POINT,
  1178. (LPVOID)pCertContext,
  1179. CRYPT_GET_URL_FROM_EXTENSION,
  1180. NULL,
  1181. &cbUrlArray,
  1182. NULL,
  1183. NULL,
  1184. NULL))
  1185. goto FailureStatusReturn;
  1186. pUrlArray=(PCRYPT_URL_ARRAY)malloc(cbUrlArray);
  1187. if(NULL == pUrlArray)
  1188. goto FailureStatusReturn;
  1189. if(!CryptGetObjectUrl(
  1190. URL_OID_CERTIFICATE_CRL_DIST_POINT,
  1191. (LPVOID)pCertContext,
  1192. CRYPT_GET_URL_FROM_EXTENSION,
  1193. pUrlArray,
  1194. &cbUrlArray,
  1195. NULL,
  1196. NULL,
  1197. NULL))
  1198. goto FailureStatusReturn;
  1199. for(dwIndex=0; dwIndex < pUrlArray->cUrl; dwIndex++)
  1200. {
  1201. if(CryptRetrieveObjectByUrlW (
  1202. pUrlArray->rgwszUrl[dwIndex],
  1203. CONTEXT_OID_CRL,
  1204. CRYPT_WIRE_ONLY_RETRIEVAL, //we should try to hit the wire
  1205. 0,
  1206. (LPVOID *)&pCRLContext,
  1207. NULL,
  1208. NULL,
  1209. NULL,
  1210. NULL))
  1211. break;
  1212. }
  1213. if(NULL==pCRLContext)
  1214. goto FailureStatusReturn;
  1215. //package the CRL in an empty PKCS7
  1216. if(!PackageBlobToPKCS7(CEP_CONTEXT_CRL, pCRLContext->pbCrlEncoded,
  1217. pCRLContext->cbCrlEncoded, ppbData, pcbData))
  1218. goto FailureStatusReturn;
  1219. //this is the signing cert to which our response should be encrypted
  1220. if(NULL==(pMsgInfo->pSigningCert=CertDuplicateCertificateContext(pCertContext)))
  1221. goto FailureStatusReturn;
  1222. fResult = TRUE;
  1223. CommonReturn:
  1224. if(pCertContext)
  1225. CertFreeCertificateContext(pCertContext);
  1226. if(pCRLContext)
  1227. CertFreeCRLContext(pCRLContext);
  1228. if(pUrlArray)
  1229. free(pUrlArray);
  1230. return fResult;
  1231. FailureStatusReturn:
  1232. //we set the error status for the return message
  1233. //and consider this http transation a success
  1234. pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE;
  1235. pMsgInfo->dwErrorInfo=dwErrorInfo;
  1236. if(ppbData)
  1237. {
  1238. if(*ppbData)
  1239. free(*ppbData);
  1240. *ppbData=NULL;
  1241. }
  1242. if(pcbData)
  1243. *pcbData=0;
  1244. fResult=TRUE;
  1245. goto CommonReturn;
  1246. ErrorReturn:
  1247. fResult=FALSE;
  1248. goto CommonReturn;
  1249. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1250. }
  1251. //--------------------------------------------------------------------------
  1252. //
  1253. // ProcessGetCert
  1254. //
  1255. //
  1256. //--------------------------------------------------------------------------
  1257. BOOL WINAPI ProcessGetCert(CEP_CA_INFO *pCAInfo,
  1258. BYTE *pbRequest,
  1259. DWORD cbRequest,
  1260. BYTE **ppbData,
  1261. DWORD *pcbData,
  1262. CEP_MESSAGE_INFO *pMsgInfo)
  1263. {
  1264. BOOL fResult = FALSE;
  1265. DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  1266. CRYPT_INTEGER_BLOB SerialNumber;
  1267. PCCERT_CONTEXT pCertContext=NULL;
  1268. if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo)
  1269. goto InvalidArgErr;
  1270. *ppbData=NULL;
  1271. *pcbData=0;
  1272. memset(&SerialNumber, 0, sizeof(CRYPT_INTEGER_BLOB));
  1273. //get the serialnumber from the request
  1274. if(!GetSerialNumberFromBlob(pbRequest,
  1275. cbRequest,
  1276. &SerialNumber))
  1277. {
  1278. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_NUMBER_FROM_MESSAGE, 1, g_pwszComputerName);
  1279. goto FailureStatusReturn;
  1280. }
  1281. //retrieve the cert context from the serialNumber
  1282. //protected by the critical Section since it uses ICertRequest interface
  1283. if(!RetrieveContextFromSerialNumber(pCAInfo, (CERT_BLOB*)&SerialNumber, &pCertContext))
  1284. {
  1285. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_GET_CERT_FROM_NUMBER, 1, g_pwszComputerName);
  1286. goto FailureStatusReturn;
  1287. }
  1288. //package it in an empty PKCS7
  1289. if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pCertContext->pbCertEncoded,
  1290. pCertContext->cbCertEncoded, ppbData, pcbData))
  1291. goto FailureStatusReturn;
  1292. //this is the signing cert to which our response should be encrypted
  1293. /* if(NULL==(pMsgInfo->pSigningCert=CertDuplicateCertificateContext(pCertContext)))
  1294. goto FailureStatusReturn; */
  1295. fResult = TRUE;
  1296. CommonReturn:
  1297. if(SerialNumber.pbData)
  1298. free(SerialNumber.pbData);
  1299. if(pCertContext)
  1300. CertFreeCertificateContext(pCertContext);
  1301. return fResult;
  1302. FailureStatusReturn:
  1303. //we set the error status for the return message
  1304. //and consider this http transation a success
  1305. pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE;
  1306. pMsgInfo->dwErrorInfo=dwErrorInfo;
  1307. if(ppbData)
  1308. {
  1309. if(*ppbData)
  1310. free(*ppbData);
  1311. *ppbData=NULL;
  1312. }
  1313. if(pcbData)
  1314. *pcbData=0;
  1315. fResult=TRUE;
  1316. goto CommonReturn;
  1317. ErrorReturn:
  1318. fResult=FALSE;
  1319. goto CommonReturn;
  1320. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1321. }
  1322. //--------------------------------------------------------------------------
  1323. //
  1324. // ProcessCertInitial
  1325. //
  1326. //
  1327. //--------------------------------------------------------------------------
  1328. BOOL ProcessCertInitial( DWORD dwRefreshDays,
  1329. CEP_CA_INFO *pCAInfo,
  1330. BYTE *pbRequest,
  1331. DWORD cbRequest,
  1332. BYTE **ppbData,
  1333. DWORD *pcbData,
  1334. CEP_MESSAGE_INFO *pMsgInfo)
  1335. {
  1336. BOOL fResult = FALSE;
  1337. DWORD dwRequestID=0;
  1338. DWORD cbCert=0;
  1339. BYTE *pbCert=NULL;
  1340. DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_CERT_ID;
  1341. long dwDisposition=0;
  1342. HRESULT hr=S_OK;
  1343. BSTR bstrCert=NULL;
  1344. if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo)
  1345. goto InvalidArgErr;
  1346. *ppbData=NULL;
  1347. *pcbData=0;
  1348. //map the trasactionID to the request ID
  1349. if(!CEPHashGetRequestID(dwRefreshDays, &(pMsgInfo->TransactionID), &dwRequestID))
  1350. {
  1351. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_TO_GET_ID, 1, g_pwszComputerName);
  1352. goto FailureStatusReturn;
  1353. }
  1354. if(S_OK != (hr = pCAInfo->pICertRequest->RetrievePending(dwRequestID,
  1355. pCAInfo->bstrCAConfig,
  1356. &dwDisposition)))
  1357. {
  1358. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_QUERY_CA, 1, g_pwszComputerName);
  1359. goto FailureStatusReturn;
  1360. }
  1361. switch(dwDisposition)
  1362. {
  1363. case CR_DISP_ISSUED:
  1364. if(S_OK != (hr = pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY,
  1365. &bstrCert)))
  1366. {
  1367. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_QUERY_CERT, 1, g_pwszComputerName);
  1368. goto FailureStatusReturn;
  1369. }
  1370. cbCert = (DWORD)SysStringByteLen(bstrCert);
  1371. pbCert = (BYTE *)bstrCert;
  1372. //package it in an empty PKCS7
  1373. if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pbCert, cbCert, ppbData, pcbData))
  1374. goto FailureStatusReturn;
  1375. pMsgInfo->dwStatus=MESSAGE_STATUS_SUCCESS;
  1376. //mark the finished for RequesetID/TransactionID pair
  1377. CEPHashMarkTransactionFinished(dwRequestID, &(pMsgInfo->TransactionID));
  1378. break;
  1379. case CR_DISP_UNDER_SUBMISSION:
  1380. pMsgInfo->dwStatus=MESSAGE_STATUS_PENDING;
  1381. break;
  1382. case CR_DISP_INCOMPLETE:
  1383. case CR_DISP_ERROR:
  1384. case CR_DISP_DENIED:
  1385. case CR_DISP_ISSUED_OUT_OF_BAND: //we consider it a failure in this case
  1386. case CR_DISP_REVOKED:
  1387. default:
  1388. //mark the finished for RequesetID/TransactionID pair
  1389. CEPHashMarkTransactionFinished(dwRequestID, &(pMsgInfo->TransactionID));
  1390. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  1391. goto FailureStatusReturn;
  1392. break;
  1393. }
  1394. fResult = TRUE;
  1395. CommonReturn:
  1396. if(bstrCert)
  1397. SysFreeString(bstrCert);
  1398. return fResult;
  1399. FailureStatusReturn:
  1400. //we set the error status for the return message
  1401. //and consider this http transation a success
  1402. pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE;
  1403. pMsgInfo->dwErrorInfo=dwErrorInfo;
  1404. *ppbData=NULL;
  1405. *pcbData=0;
  1406. fResult=TRUE;
  1407. goto CommonReturn;
  1408. ErrorReturn:
  1409. fResult=FALSE;
  1410. goto CommonReturn;
  1411. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1412. }
  1413. //--------------------------------------------------------------------------
  1414. //
  1415. // PackageBlobToPKCS7
  1416. //
  1417. // Precondition: ppbData and pcbData is guaranteed not to be NULL
  1418. //--------------------------------------------------------------------------
  1419. BOOL PackageBlobToPKCS7(DWORD dwCEP_Context,
  1420. BYTE *pbEncoded,
  1421. DWORD cbEncoded,
  1422. BYTE **ppbData,
  1423. DWORD *pcbData)
  1424. {
  1425. BOOL fResult=FALSE;
  1426. CERT_BLOB CertBlob;
  1427. HCERTSTORE hCertStore=NULL;
  1428. if((!pbEncoded) || (0==cbEncoded))
  1429. goto InvalidArgErr;
  1430. *ppbData=NULL;
  1431. *pcbData=0;
  1432. if(NULL == (hCertStore = CertOpenStore(
  1433. CERT_STORE_PROV_MEMORY,
  1434. ENCODE_TYPE,
  1435. NULL,
  1436. 0,
  1437. NULL)))
  1438. goto TraceErr;
  1439. switch(dwCEP_Context)
  1440. {
  1441. case CEP_CONTEXT_CERT:
  1442. if(!CertAddEncodedCertificateToStore(hCertStore,
  1443. ENCODE_TYPE,
  1444. pbEncoded,
  1445. cbEncoded,
  1446. CERT_STORE_ADD_ALWAYS,
  1447. NULL))
  1448. goto TraceErr;
  1449. break;
  1450. case CEP_CONTEXT_CRL:
  1451. if(!CertAddEncodedCRLToStore(hCertStore,
  1452. ENCODE_TYPE,
  1453. pbEncoded,
  1454. cbEncoded,
  1455. CERT_STORE_ADD_ALWAYS,
  1456. NULL))
  1457. goto TraceErr;
  1458. break;
  1459. default:
  1460. goto InvalidArgErr;
  1461. break;
  1462. }
  1463. CertBlob.cbData=0;
  1464. CertBlob.pbData=NULL;
  1465. if(!CertSaveStore(hCertStore,
  1466. ENCODE_TYPE,
  1467. CERT_STORE_SAVE_AS_PKCS7,
  1468. CERT_STORE_SAVE_TO_MEMORY,
  1469. &CertBlob,
  1470. 0))
  1471. goto TraceErr;
  1472. CertBlob.pbData = (BYTE *)malloc(CertBlob.cbData);
  1473. if(NULL == CertBlob.pbData)
  1474. goto MemoryErr;
  1475. if(!CertSaveStore(hCertStore,
  1476. ENCODE_TYPE,
  1477. CERT_STORE_SAVE_AS_PKCS7,
  1478. CERT_STORE_SAVE_TO_MEMORY,
  1479. &CertBlob,
  1480. 0))
  1481. goto TraceErr;
  1482. //copy the memory
  1483. *ppbData=CertBlob.pbData;
  1484. *pcbData=CertBlob.cbData;
  1485. CertBlob.pbData=NULL;
  1486. fResult = TRUE;
  1487. CommonReturn:
  1488. if(CertBlob.pbData)
  1489. free(CertBlob.pbData);
  1490. if(hCertStore)
  1491. CertCloseStore(hCertStore, 0);
  1492. return fResult;
  1493. ErrorReturn:
  1494. fResult=FALSE;
  1495. goto CommonReturn;
  1496. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1497. TRACE_ERROR(TraceErr);
  1498. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1499. }
  1500. //--------------------------------------------------------------------------
  1501. //
  1502. // CEPRetrievePasswordFromRequest
  1503. //
  1504. //--------------------------------------------------------------------------
  1505. BOOL WINAPI CEPRetrievePasswordFromRequest(BYTE *pbRequest,
  1506. DWORD cbRequest,
  1507. LPWSTR *ppwszPassword,
  1508. DWORD *pdwUsage)
  1509. {
  1510. BOOL fResult=FALSE;
  1511. DWORD cbData=0;
  1512. DWORD dwIndex=0;
  1513. DWORD cbNameValue=0;
  1514. DWORD dwExt=0;
  1515. DWORD cbExtensions=0;
  1516. DWORD cbSize=0;
  1517. CERT_REQUEST_INFO *pCertRequestInfo=NULL;
  1518. CERT_NAME_VALUE *pbNameValue=NULL;
  1519. CERT_EXTENSIONS *pExtensions=NULL;
  1520. CRYPT_BIT_BLOB *pKeyUsage=NULL;
  1521. *ppwszPassword=NULL;
  1522. *pdwUsage=0;
  1523. if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED,
  1524. pbRequest,
  1525. cbRequest,
  1526. (void **)&pCertRequestInfo,
  1527. &cbData))
  1528. goto TraceErr;
  1529. //get the key usage
  1530. for(dwIndex=0; dwIndex < pCertRequestInfo->cAttribute; dwIndex++)
  1531. {
  1532. if((0 == strcmp(szOID_RSA_certExtensions, pCertRequestInfo->rgAttribute[dwIndex].pszObjId)) ||
  1533. (0 == strcmp(szOID_CERT_EXTENSIONS, pCertRequestInfo->rgAttribute[dwIndex].pszObjId))
  1534. )
  1535. {
  1536. if(CEPAllocAndDecode(X509_EXTENSIONS,
  1537. pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].pbData,
  1538. pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].cbData,
  1539. (void **)&pExtensions,
  1540. &cbExtensions))
  1541. {
  1542. for(dwExt=0; dwExt < pExtensions->cExtension; dwExt++)
  1543. {
  1544. if(0==strcmp(szOID_KEY_USAGE, pExtensions->rgExtension[dwExt].pszObjId))
  1545. {
  1546. if(CEPAllocAndDecode(X509_KEY_USAGE,
  1547. pExtensions->rgExtension[dwExt].Value.pbData,
  1548. pExtensions->rgExtension[dwExt].Value.cbData,
  1549. (void **)&pKeyUsage,
  1550. &cbSize))
  1551. {
  1552. if(pKeyUsage->pbData)
  1553. {
  1554. if(CERT_DIGITAL_SIGNATURE_KEY_USAGE & (pKeyUsage->pbData[0]))
  1555. (*pdwUsage) = (*pdwUsage) | CEP_REQUEST_SIGNATURE;
  1556. if(CERT_KEY_ENCIPHERMENT_KEY_USAGE & (pKeyUsage->pbData[0]))
  1557. (*pdwUsage) = (*pdwUsage) | CEP_REQUEST_EXCHANGE;
  1558. }
  1559. }
  1560. if(pKeyUsage)
  1561. free(pKeyUsage);
  1562. pKeyUsage=NULL;
  1563. cbSize=0;
  1564. }
  1565. }
  1566. }
  1567. if(pExtensions)
  1568. free(pExtensions);
  1569. pExtensions=NULL;
  1570. cbExtensions=0;
  1571. }
  1572. }
  1573. //get the password
  1574. for(dwIndex=0; dwIndex < pCertRequestInfo->cAttribute; dwIndex++)
  1575. {
  1576. if(0 == strcmp(szOID_RSA_challengePwd,
  1577. pCertRequestInfo->rgAttribute[dwIndex].pszObjId))
  1578. break;
  1579. }
  1580. //the password is not required to be present in this function
  1581. if(dwIndex != pCertRequestInfo->cAttribute)
  1582. {
  1583. if(!CEPAllocAndDecode(X509_UNICODE_ANY_STRING,
  1584. pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].pbData,
  1585. pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].cbData,
  1586. (void **)&pbNameValue,
  1587. &cbNameValue))
  1588. goto TraceErr;
  1589. if(CERT_RDN_PRINTABLE_STRING != (pbNameValue->dwValueType))
  1590. goto InvalidArgErr;
  1591. cbData=wcslen((LPWSTR)(pbNameValue->Value.pbData));
  1592. *ppwszPassword=(LPWSTR)malloc(sizeof(WCHAR) * (cbData + 1));
  1593. if(NULL==(*ppwszPassword))
  1594. goto MemoryErr;
  1595. wcscpy(*ppwszPassword,(LPWSTR)(pbNameValue->Value.pbData));
  1596. }
  1597. fResult=TRUE;
  1598. CommonReturn:
  1599. if(pExtensions)
  1600. free(pExtensions);
  1601. if(pKeyUsage)
  1602. free(pKeyUsage);
  1603. if(pbNameValue)
  1604. free(pbNameValue);
  1605. if(pCertRequestInfo)
  1606. free(pCertRequestInfo);
  1607. return fResult;
  1608. ErrorReturn:
  1609. fResult=FALSE;
  1610. goto CommonReturn;
  1611. TRACE_ERROR(TraceErr);
  1612. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1613. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1614. }
  1615. //--------------------------------------------------------------------------
  1616. //
  1617. // AltNameExist
  1618. //
  1619. // Return TRUE is szOID_SUBJECT_ALT_NAME2 is present in the PKCS10
  1620. // FALSE otherwise
  1621. //--------------------------------------------------------------------------
  1622. BOOL WINAPI AltNameExist(BYTE *pbRequest, DWORD cbRequest)
  1623. {
  1624. BOOL fResult = FALSE;
  1625. DWORD cbData=0;
  1626. DWORD cbExtensions=0;
  1627. DWORD dwIndex=0;
  1628. DWORD dwExt=0;
  1629. CERT_REQUEST_INFO *pCertRequestInfo=NULL;
  1630. CERT_EXTENSIONS *pExtensions=NULL;
  1631. if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED,
  1632. pbRequest,
  1633. cbRequest,
  1634. (void **)&pCertRequestInfo,
  1635. &cbData))
  1636. goto ErrorReturn;
  1637. for(dwIndex=0; dwIndex < pCertRequestInfo->cAttribute; dwIndex++)
  1638. {
  1639. if((0 == strcmp(szOID_RSA_certExtensions, pCertRequestInfo->rgAttribute[dwIndex].pszObjId)) ||
  1640. (0 == strcmp(szOID_CERT_EXTENSIONS, pCertRequestInfo->rgAttribute[dwIndex].pszObjId))
  1641. )
  1642. {
  1643. if(CEPAllocAndDecode(X509_EXTENSIONS,
  1644. pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].pbData,
  1645. pCertRequestInfo->rgAttribute[dwIndex].rgValue[0].cbData,
  1646. (void **)&pExtensions,
  1647. &cbExtensions))
  1648. {
  1649. for(dwExt=0; dwExt < pExtensions->cExtension; dwExt++)
  1650. {
  1651. if(0==strcmp(szOID_SUBJECT_ALT_NAME2, pExtensions->rgExtension[dwExt].pszObjId))
  1652. {
  1653. fResult=TRUE;
  1654. goto CommonReturn;
  1655. }
  1656. }
  1657. }
  1658. if(pExtensions)
  1659. free(pExtensions);
  1660. pExtensions=NULL;
  1661. cbExtensions=0;
  1662. }
  1663. }
  1664. CommonReturn:
  1665. if(pExtensions)
  1666. free(pExtensions);
  1667. if(pCertRequestInfo)
  1668. free(pCertRequestInfo);
  1669. return fResult;
  1670. ErrorReturn:
  1671. fResult=FALSE;
  1672. goto CommonReturn;
  1673. }
  1674. //--------------------------------------------------------------------------
  1675. //
  1676. // CEPAllocAndEncode
  1677. //
  1678. //--------------------------------------------------------------------------
  1679. BOOL WINAPI CEPAllocAndEncode(LPCSTR lpszStructType,
  1680. void *pStructInfo,
  1681. BYTE **ppbEncoded,
  1682. DWORD *pcbEncoded)
  1683. {
  1684. BOOL fResult=FALSE;
  1685. *pcbEncoded=0;
  1686. if(!CryptEncodeObject(ENCODE_TYPE,
  1687. lpszStructType,
  1688. pStructInfo,
  1689. NULL,
  1690. pcbEncoded))
  1691. goto TraceErr;
  1692. *ppbEncoded=(BYTE *)malloc(*pcbEncoded);
  1693. if(NULL==(*ppbEncoded))
  1694. goto MemoryErr;
  1695. if(!CryptEncodeObject(ENCODE_TYPE,
  1696. lpszStructType,
  1697. pStructInfo,
  1698. *ppbEncoded,
  1699. pcbEncoded))
  1700. goto TraceErr;
  1701. fResult = TRUE;
  1702. CommonReturn:
  1703. return fResult;
  1704. ErrorReturn:
  1705. if(*ppbEncoded)
  1706. {
  1707. free(*ppbEncoded);
  1708. *ppbEncoded=NULL;
  1709. }
  1710. *pcbEncoded=0;
  1711. fResult=FALSE;
  1712. goto CommonReturn;
  1713. TRACE_ERROR(TraceErr);
  1714. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1715. }
  1716. //--------------------------------------------------------------------------
  1717. //
  1718. // ConvertIPStringToBinary
  1719. //
  1720. // Conver the IP address in the format of "xxx.xx.xx.xx" to an arry of
  1721. // bytes. One byte per xxx
  1722. //--------------------------------------------------------------------------
  1723. BOOL ConvertIPStringToBinary(LPWSTR pwszIP,
  1724. CRYPT_DATA_BLOB *pIPAddress)
  1725. {
  1726. BOOL fResult = FALSE;
  1727. LPWSTR pwszTok=NULL;
  1728. DWORD cTok=0;
  1729. DWORD dwIndex=0;
  1730. if(!pwszIP || !pIPAddress)
  1731. goto InvalidArgErr;
  1732. pIPAddress->pbData=NULL;
  1733. pIPAddress->cbData=0;
  1734. pwszTok=wcstok(pwszIP, L".");
  1735. while(NULL != pwszTok)
  1736. {
  1737. cTok++;
  1738. pwszTok=wcstok(NULL, L".");
  1739. }
  1740. pIPAddress->pbData=(BYTE *)malloc(cTok);
  1741. if(NULL==pIPAddress->pbData)
  1742. goto MemoryErr;
  1743. pIPAddress->cbData=cTok;
  1744. pwszTok=pwszIP;
  1745. for(dwIndex=0; dwIndex < cTok; dwIndex++)
  1746. {
  1747. pIPAddress->pbData[dwIndex]=(BYTE)_wtol(pwszTok);
  1748. pwszTok=pwszTok+wcslen(pwszTok)+1;
  1749. }
  1750. fResult = TRUE;
  1751. CommonReturn:
  1752. return fResult;
  1753. ErrorReturn:
  1754. fResult=FALSE;
  1755. goto CommonReturn;
  1756. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1757. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1758. }
  1759. //--------------------------------------------------------------------------
  1760. //
  1761. // GetAltNameElement
  1762. //
  1763. // We create the subject alternative extension based on the PKCS10.
  1764. // unstructedName(DNS name) and unstructedAddress (IP address) are included.
  1765. // At lease one element should be present.
  1766. //--------------------------------------------------------------------------
  1767. BOOL WINAPI GetAltNameElement(BYTE *pb10,
  1768. DWORD cb10,
  1769. LPWSTR *ppwszDNS,
  1770. CRYPT_DATA_BLOB *pIPAddress)
  1771. {
  1772. BOOL fResult = FALSE;
  1773. DWORD cbRequestInfo=0;
  1774. DWORD cbNameInfo=0;
  1775. DWORD dwRDN=0;
  1776. DWORD dwAttr=0;
  1777. PCERT_RDN_ATTR pAttr=NULL;
  1778. DWORD cb=0;
  1779. CERT_REQUEST_INFO *pRequestInfo=NULL;
  1780. CERT_NAME_INFO *pNameInfo=NULL;
  1781. if(!pb10 || !ppwszDNS || !pIPAddress)
  1782. goto InvalidArgErr;
  1783. *ppwszDNS=NULL;
  1784. pIPAddress->cbData=0;
  1785. pIPAddress->pbData=NULL;
  1786. if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED,
  1787. pb10,
  1788. cb10,
  1789. (void **)&pRequestInfo,
  1790. &cbRequestInfo))
  1791. goto TraceErr;
  1792. if(!CEPAllocAndDecode(X509_UNICODE_NAME,
  1793. pRequestInfo->Subject.pbData,
  1794. pRequestInfo->Subject.cbData,
  1795. (void **)&pNameInfo,
  1796. &cbNameInfo))
  1797. goto TraceErr;
  1798. for(dwRDN=0; dwRDN<pNameInfo->cRDN; dwRDN++)
  1799. {
  1800. for(dwAttr=0; dwAttr<pNameInfo->rgRDN[dwRDN].cRDNAttr; dwAttr++)
  1801. {
  1802. pAttr=&(pNameInfo->rgRDN[dwRDN].rgRDNAttr[dwAttr]);
  1803. //we are happy if we have found both the IPAddress and the fqdn
  1804. if((*ppwszDNS) && (pIPAddress->pbData))
  1805. break;
  1806. if((NULL==*ppwszDNS) && (0 == strcmp(szOID_RSA_unstructName,pAttr->pszObjId)))
  1807. {
  1808. cb=sizeof(WCHAR) * (1+wcslen((LPWSTR)(pAttr->Value.pbData)));
  1809. *ppwszDNS=(LPWSTR)malloc(cb);
  1810. if(NULL == *ppwszDNS)
  1811. goto MemoryErr;
  1812. wcscpy(*ppwszDNS, (LPWSTR)(pAttr->Value.pbData));
  1813. }
  1814. else
  1815. {
  1816. if((NULL==pIPAddress->pbData) && (0 == strcmp(szOID_RSA_unstructAddr,pAttr->pszObjId)))
  1817. {
  1818. if(!ConvertIPStringToBinary((LPWSTR)(pAttr->Value.pbData),
  1819. pIPAddress))
  1820. goto TraceErr;
  1821. }
  1822. }
  1823. }
  1824. }
  1825. //we need to have some element
  1826. if((NULL == *ppwszDNS) && (NULL==pIPAddress->pbData))
  1827. goto InvalidArgErr;
  1828. fResult = TRUE;
  1829. CommonReturn:
  1830. if(pNameInfo)
  1831. free(pNameInfo);
  1832. if(pRequestInfo)
  1833. free(pRequestInfo);
  1834. return fResult;
  1835. ErrorReturn:
  1836. if(ppwszDNS)
  1837. {
  1838. if(*ppwszDNS)
  1839. {
  1840. free(*ppwszDNS);
  1841. *ppwszDNS=NULL;
  1842. }
  1843. }
  1844. if(pIPAddress)
  1845. {
  1846. if(pIPAddress->pbData)
  1847. {
  1848. free(pIPAddress->pbData);
  1849. pIPAddress->pbData=NULL;
  1850. }
  1851. pIPAddress->cbData=0;
  1852. }
  1853. fResult=FALSE;
  1854. goto CommonReturn;
  1855. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1856. TRACE_ERROR(TraceErr);
  1857. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1858. }
  1859. //--------------------------------------------------------------------------
  1860. //
  1861. // CreateAltNameExtenions
  1862. //
  1863. //--------------------------------------------------------------------------
  1864. BOOL WINAPI CreateAltNameExtenions(LPWSTR pwszDNS,
  1865. CRYPT_DATA_BLOB *pIPAddress,
  1866. BYTE **ppbExt,
  1867. DWORD *pcbExt)
  1868. {
  1869. BOOL fResult = FALSE;
  1870. CERT_ALT_NAME_INFO AltNameInfo;
  1871. CERT_ALT_NAME_ENTRY rgAltNameEntry[2];
  1872. DWORD cAltNameEntry=0;
  1873. //DNS name
  1874. if(pwszDNS)
  1875. {
  1876. rgAltNameEntry[cAltNameEntry].dwAltNameChoice=CERT_ALT_NAME_DNS_NAME;
  1877. rgAltNameEntry[cAltNameEntry].pwszDNSName=pwszDNS;
  1878. cAltNameEntry++;
  1879. }
  1880. //IP address
  1881. if(pIPAddress->pbData)
  1882. {
  1883. rgAltNameEntry[cAltNameEntry].dwAltNameChoice=CERT_ALT_NAME_IP_ADDRESS;
  1884. rgAltNameEntry[cAltNameEntry].IPAddress.cbData=pIPAddress->cbData;
  1885. rgAltNameEntry[cAltNameEntry].IPAddress.pbData=pIPAddress->pbData;
  1886. cAltNameEntry++;
  1887. }
  1888. memset(&AltNameInfo, 0, sizeof(CERT_ALT_NAME_INFO));
  1889. AltNameInfo.cAltEntry=cAltNameEntry;
  1890. AltNameInfo.rgAltEntry=rgAltNameEntry;
  1891. if(!CEPAllocAndEncode(szOID_SUBJECT_ALT_NAME2,
  1892. &AltNameInfo,
  1893. ppbExt,
  1894. pcbExt))
  1895. goto TraceErr;
  1896. fResult = TRUE;
  1897. CommonReturn:
  1898. return fResult;
  1899. ErrorReturn:
  1900. fResult=FALSE;
  1901. goto CommonReturn;
  1902. TRACE_ERROR(TraceErr);
  1903. }
  1904. //--------------------------------------------------------------------------
  1905. //
  1906. // AddAltNameInRequest
  1907. //
  1908. //--------------------------------------------------------------------------
  1909. BOOL WINAPI AddAltNameInRequest(PCCERT_CONTEXT pRACert,
  1910. BYTE *pb10,
  1911. DWORD cb10,
  1912. LPWSTR pwszDNS,
  1913. CRYPT_DATA_BLOB *pIPAddress,
  1914. BYTE **ppb7,
  1915. DWORD *pcb7)
  1916. {
  1917. BOOL fResult = FALSE;
  1918. DWORD cbExt=0;
  1919. CERT_EXTENSIONS Exts;
  1920. CERT_EXTENSION Ext;
  1921. DWORD cbAllExt=0;
  1922. CRYPT_SIGN_MESSAGE_PARA signPara;
  1923. CRYPT_ATTRIBUTE AuthAttr;
  1924. PCCRYPT_OID_INFO pOIDInfo=NULL;
  1925. ALG_ID AlgValue=CALG_SHA1;
  1926. CRYPT_ATTR_BLOB AttrBlob;
  1927. BYTE *pbExt=NULL;
  1928. BYTE *pbAllExt=NULL;
  1929. if(!pRACert || !pb10 || !ppb7 || !pcb7)
  1930. goto InvalidArgErr;
  1931. *ppb7=NULL;
  1932. *pcb7=0;
  1933. if(!CreateAltNameExtenions(pwszDNS, pIPAddress, &pbExt, &cbExt))
  1934. goto TraceErr;
  1935. Exts.cExtension=1;
  1936. Exts.rgExtension=&Ext;
  1937. Ext.pszObjId=szOID_SUBJECT_ALT_NAME2;
  1938. Ext.fCritical=TRUE;
  1939. Ext.Value.pbData=pbExt;
  1940. Ext.Value.cbData=cbExt;
  1941. if(!CEPAllocAndEncode(X509_EXTENSIONS,
  1942. &Exts,
  1943. &pbAllExt,
  1944. &cbAllExt))
  1945. goto TraceErr;
  1946. AuthAttr.pszObjId=szOID_CERT_EXTENSIONS;
  1947. AuthAttr.cValue=1;
  1948. AuthAttr.rgValue=&AttrBlob;
  1949. AttrBlob.pbData=pbAllExt;
  1950. AttrBlob.cbData=cbAllExt;
  1951. memset(&signPara, 0, sizeof(signPara));
  1952. signPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
  1953. signPara.dwMsgEncodingType = ENCODE_TYPE;
  1954. signPara.pSigningCert = pRACert;
  1955. signPara.cMsgCert = 1;
  1956. signPara.rgpMsgCert = &pRACert;
  1957. signPara.cAuthAttr = 1;
  1958. signPara.rgAuthAttr = &AuthAttr;
  1959. if(pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
  1960. &AlgValue,
  1961. CRYPT_HASH_ALG_OID_GROUP_ID))
  1962. signPara.HashAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID);
  1963. else
  1964. signPara.HashAlgorithm.pszObjId=szOID_OIWSEC_sha1;
  1965. if(!CryptSignMessage(
  1966. &signPara,
  1967. FALSE,
  1968. 1,
  1969. (const BYTE **) &pb10,
  1970. &cb10,
  1971. NULL,
  1972. pcb7))
  1973. goto TraceErr;
  1974. *ppb7=(BYTE *)malloc(*pcb7);
  1975. if(NULL==(*ppb7))
  1976. goto MemoryErr;
  1977. if(!CryptSignMessage(
  1978. &signPara,
  1979. FALSE,
  1980. 1,
  1981. (const BYTE **) &pb10,
  1982. &cb10,
  1983. *ppb7,
  1984. pcb7))
  1985. goto TraceErr;
  1986. fResult = TRUE;
  1987. CommonReturn:
  1988. if(pbAllExt)
  1989. free(pbAllExt);
  1990. if(pbExt)
  1991. free(pbExt);
  1992. return fResult;
  1993. ErrorReturn:
  1994. if(ppb7)
  1995. {
  1996. if(*ppb7)
  1997. {
  1998. free(*ppb7);
  1999. *ppb7=NULL;
  2000. }
  2001. }
  2002. if(pcb7)
  2003. *pcb7=0;
  2004. fResult=FALSE;
  2005. goto CommonReturn;
  2006. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2007. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2008. TRACE_ERROR(TraceErr);
  2009. }
  2010. //--------------------------------------------------------------------------
  2011. //
  2012. // MakePKCS7Request
  2013. //
  2014. //--------------------------------------------------------------------------
  2015. BOOL WINAPI MakePKCS7Request(PCCERT_CONTEXT pRACert,
  2016. BYTE *pb10,
  2017. DWORD cb10,
  2018. BYTE **ppb7,
  2019. DWORD *pcb7)
  2020. {
  2021. BOOL fResult = FALSE;
  2022. CRYPT_SIGN_MESSAGE_PARA signPara;
  2023. PCCRYPT_OID_INFO pOIDInfo=NULL;
  2024. ALG_ID AlgValue=CALG_SHA1;
  2025. if(!pRACert || !pb10 || !ppb7 || !pcb7)
  2026. goto InvalidArgErr;
  2027. *ppb7=NULL;
  2028. *pcb7=0;
  2029. memset(&signPara, 0, sizeof(signPara));
  2030. signPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
  2031. signPara.dwMsgEncodingType = ENCODE_TYPE;
  2032. signPara.pSigningCert = pRACert;
  2033. signPara.cMsgCert = 1;
  2034. signPara.rgpMsgCert = &pRACert;
  2035. signPara.cAuthAttr = 0;
  2036. signPara.rgAuthAttr = NULL;
  2037. if(pOIDInfo=CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
  2038. &AlgValue,
  2039. CRYPT_HASH_ALG_OID_GROUP_ID))
  2040. signPara.HashAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID);
  2041. else
  2042. signPara.HashAlgorithm.pszObjId=szOID_OIWSEC_sha1;
  2043. if(!CryptSignMessage(
  2044. &signPara,
  2045. FALSE,
  2046. 1,
  2047. (const BYTE **) &pb10,
  2048. &cb10,
  2049. NULL,
  2050. pcb7))
  2051. goto TraceErr;
  2052. *ppb7=(BYTE *)malloc(*pcb7);
  2053. if(NULL==(*ppb7))
  2054. goto MemoryErr;
  2055. if(!CryptSignMessage(
  2056. &signPara,
  2057. FALSE,
  2058. 1,
  2059. (const BYTE **) &pb10,
  2060. &cb10,
  2061. *ppb7,
  2062. pcb7))
  2063. goto TraceErr;
  2064. fResult = TRUE;
  2065. CommonReturn:
  2066. return fResult;
  2067. ErrorReturn:
  2068. if(ppb7)
  2069. {
  2070. if(*ppb7)
  2071. {
  2072. free(*ppb7);
  2073. *ppb7=NULL;
  2074. }
  2075. }
  2076. if(pcb7)
  2077. *pcb7=0;
  2078. fResult=FALSE;
  2079. goto CommonReturn;
  2080. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2081. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2082. TRACE_ERROR(TraceErr);
  2083. }
  2084. /*//--------------------------------------------------------------------------
  2085. //
  2086. // GetLogonInfoFromValue
  2087. //
  2088. // The pwszString can be of format "name;password" or "domain\name;password"
  2089. //
  2090. //--------------------------------------------------------------------------
  2091. BOOL GetLogonInfoFromValue(PCCERT_CONTEXT pRAEncrypt,
  2092. LPWSTR pwszString,
  2093. LPWSTR *ppwszDomain,
  2094. LPWSTR *ppwszUser,
  2095. LPWSTR *ppwszPassword)
  2096. {
  2097. BOOL fResult=FALSE;
  2098. LPWSTR pwsz=NULL;
  2099. BOOL fDomain=FALSE;
  2100. BOOL fPassword=FALSE;
  2101. LPWSTR pwszPlainText=NULL;
  2102. *ppwszDomain=NULL;
  2103. *ppwszUser=NULL;
  2104. *ppwszPassword=NULL;
  2105. if(NULL==pwszString)
  2106. goto InvalidArgErr;
  2107. if(0 == wcslen(pwszString))
  2108. goto InvalidArgErr;
  2109. for(pwsz=pwszString; *pwsz!=L'\0'; pwsz++)
  2110. {
  2111. if(*pwsz==L'\\')
  2112. {
  2113. if(fDomain)
  2114. goto InvalidArgErr;
  2115. fDomain=TRUE;
  2116. *pwsz='\0';
  2117. }
  2118. else
  2119. {
  2120. if(*pwsz==L';')
  2121. {
  2122. if(fPassword)
  2123. goto InvalidArgErr;
  2124. fPassword=TRUE;
  2125. *pwsz='\0';
  2126. }
  2127. }
  2128. }
  2129. //have to have userName and password.
  2130. //One and only one ";" should be found
  2131. if(!fPassword)
  2132. goto InvalidArgErr;
  2133. //one or no "\" should be found
  2134. if(fDomain)
  2135. {
  2136. *ppwszDomain=pwszString;
  2137. *ppwszUser=*ppwszDomain + wcslen(*ppwszDomain) + 1;
  2138. }
  2139. else
  2140. {
  2141. *ppwszDomain=NULL;
  2142. *ppwszUser=pwszString;
  2143. }
  2144. *ppwszPassword = *ppwszUser + wcslen(*ppwszUser) + 1;
  2145. if(fDomain)
  2146. {
  2147. if(L'\0'==(**ppwszDomain))
  2148. goto InvalidArgErr;
  2149. }
  2150. if((L'\0'==(**ppwszUser)) || (L'\0'==(**ppwszPassword)))
  2151. goto InvalidArgErr;
  2152. //convert the encrypted password to the plain text form
  2153. if(!CEPDecryptPassword(pRAEncrypt,
  2154. *ppwszPassword,
  2155. &pwszPlainText))
  2156. goto TraceErr;
  2157. *ppwszPassword=pwszPlainText;
  2158. fResult = TRUE;
  2159. CommonReturn:
  2160. return fResult;
  2161. ErrorReturn:
  2162. *ppwszDomain=NULL;
  2163. *ppwszUser=NULL;
  2164. *ppwszPassword=NULL;
  2165. fResult=FALSE;
  2166. goto CommonReturn;
  2167. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2168. TRACE_ERROR(TraceErr);
  2169. } */
  2170. /*//--------------------------------------------------------------------------
  2171. //
  2172. // CEPGetTokenFromPKCS10
  2173. //
  2174. // If fPassword is TRUE, an impersonation has to occur.
  2175. //--------------------------------------------------------------------------
  2176. BOOL CEPGetTokenFromPKCS10(BOOL fPassword,
  2177. PCCERT_CONTEXT pRAEncrypt,
  2178. BYTE *pbRequest,
  2179. DWORD cbRequest,
  2180. HANDLE *phToken)
  2181. {
  2182. BOOL fResult=FALSE;
  2183. DWORD cbRequestInfo=0;
  2184. DWORD dwIndex=0;
  2185. CRYPT_ATTRIBUTE *pAttr=NULL;
  2186. DWORD cbData=0;
  2187. LPWSTR pwszDomain=NULL;
  2188. LPWSTR pwszUserName=NULL;
  2189. LPWSTR pwszPassword=NULL;
  2190. CERT_REQUEST_INFO *pRequestInfo=NULL;
  2191. CERT_NAME_VALUE *pCertNameValue=NULL;
  2192. *phToken=NULL;
  2193. if((!pbRequest) || (0==cbRequest))
  2194. goto InvalidArgErr;
  2195. if(!CEPAllocAndDecode(X509_CERT_REQUEST_TO_BE_SIGNED,
  2196. pbRequest,
  2197. cbRequest,
  2198. (void **)&pRequestInfo,
  2199. &cbRequestInfo))
  2200. goto TraceErr;
  2201. for(dwIndex=0; dwIndex < pRequestInfo->cAttribute; dwIndex++)
  2202. {
  2203. if(0 == strcmp(szOID_RSA_challengePwd, (pRequestInfo->rgAttribute[dwIndex]).pszObjId))
  2204. {
  2205. pAttr= &(pRequestInfo->rgAttribute[dwIndex]);
  2206. break;
  2207. }
  2208. }
  2209. if(NULL==pAttr)
  2210. {
  2211. if(fPassword)
  2212. goto InvalidArgErr;
  2213. else
  2214. {
  2215. *phToken=NULL;
  2216. fResult=TRUE;
  2217. goto CommonReturn;
  2218. }
  2219. }
  2220. if(CEPAllocAndDecode(X509_UNICODE_ANY_STRING,
  2221. pAttr->rgValue[0].pbData,
  2222. pAttr->rgValue[0].cbData,
  2223. (void **)&pCertNameValue,
  2224. &cbData))
  2225. {
  2226. if(GetLogonInfoFromValue(pRAEncrypt,
  2227. (LPWSTR)(pCertNameValue->Value.pbData),
  2228. &pwszDomain,
  2229. &pwszUserName,
  2230. &pwszPassword))
  2231. {
  2232. if(!LogonUserW(pwszUserName,
  2233. pwszDomain,
  2234. pwszPassword,
  2235. LOGON32_LOGON_INTERACTIVE,
  2236. LOGON32_PROVIDER_DEFAULT,
  2237. phToken))
  2238. *phToken=NULL;
  2239. }
  2240. }
  2241. if(NULL == *phToken)
  2242. {
  2243. if(fPassword)
  2244. goto InvalidArgErr;
  2245. }
  2246. fResult = TRUE;
  2247. CommonReturn:
  2248. if(pRequestInfo)
  2249. free(pRequestInfo);
  2250. if(pCertNameValue)
  2251. free(pCertNameValue);
  2252. return fResult;
  2253. ErrorReturn:
  2254. fResult=FALSE;
  2255. goto CommonReturn;
  2256. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2257. TRACE_ERROR(TraceErr);
  2258. } */
  2259. //--------------------------------------------------------------------------
  2260. //
  2261. // CEPCopyRequestAndRequestID
  2262. //
  2263. //--------------------------------------------------------------------------
  2264. BOOL WINAPI CEPCopyRequestAndRequestID(BYTE *pbRequest,
  2265. DWORD cbRequest,
  2266. DWORD dwRequestID)
  2267. {
  2268. BOOL fResult=FALSE;
  2269. BYTE pbHash[CEP_MD5_HASH_SIZE];
  2270. DWORD cbData=0;
  2271. cbData=CEP_MD5_HASH_SIZE;
  2272. if(!CryptHashCertificate(
  2273. NULL,
  2274. CALG_MD5,
  2275. 0,
  2276. pbRequest,
  2277. cbRequest,
  2278. pbHash,
  2279. &cbData))
  2280. goto TraceErr;
  2281. if(!CEPRequestAddHashAndRequestID(pbHash, dwRequestID))
  2282. goto TraceErr;
  2283. fResult = TRUE;
  2284. CommonReturn:
  2285. return fResult;
  2286. ErrorReturn:
  2287. fResult=FALSE;
  2288. goto CommonReturn;
  2289. TRACE_ERROR(TraceErr);
  2290. }
  2291. //--------------------------------------------------------------------------
  2292. //
  2293. // CEPGetCertFromPKCS10
  2294. //
  2295. //--------------------------------------------------------------------------
  2296. BOOL WINAPI CEPGetCertFromPKCS10(CEP_CA_INFO *pCAInfo,
  2297. BYTE *pbRequest,
  2298. DWORD cbRequest,
  2299. BYTE **ppbData,
  2300. DWORD *pcbData,
  2301. CEP_MESSAGE_INFO *pMsgInfo)
  2302. {
  2303. BOOL fResult = FALSE;
  2304. DWORD dwRequestID=0;
  2305. DWORD cbCert=0;
  2306. BYTE *pbCert=NULL;
  2307. DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_CERT_ID;
  2308. long dwDisposition=0;
  2309. BYTE pbHash[CEP_MD5_HASH_SIZE];
  2310. DWORD cbData=0;
  2311. BSTR bstrCert=NULL;
  2312. if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo)
  2313. goto InvalidArgErr;
  2314. *ppbData=NULL;
  2315. *pcbData=0;
  2316. cbData=CEP_MD5_HASH_SIZE;
  2317. if(!CryptHashCertificate(
  2318. NULL,
  2319. CALG_MD5,
  2320. 0,
  2321. pbRequest,
  2322. cbRequest,
  2323. pbHash,
  2324. &cbData))
  2325. goto TraceErr;
  2326. if(!CEPRequestRetrieveRequestIDFromHash(pbHash, &dwRequestID))
  2327. goto InvalidArgErr;
  2328. if(S_OK != pCAInfo->pICertRequest->RetrievePending(dwRequestID,
  2329. pCAInfo->bstrCAConfig,
  2330. &dwDisposition))
  2331. goto InvalidArgErr;
  2332. switch(dwDisposition)
  2333. {
  2334. case CR_DISP_ISSUED:
  2335. if(S_OK != pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY,
  2336. &bstrCert))
  2337. goto FailureStatusReturn;
  2338. cbCert = (DWORD)SysStringByteLen(bstrCert);
  2339. pbCert = (BYTE *)bstrCert;
  2340. //package it in an empty PKCS7
  2341. if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pbCert, cbCert, ppbData, pcbData))
  2342. goto FailureStatusReturn;
  2343. pMsgInfo->dwStatus=MESSAGE_STATUS_SUCCESS;
  2344. break;
  2345. case CR_DISP_UNDER_SUBMISSION:
  2346. pMsgInfo->dwStatus=MESSAGE_STATUS_PENDING;
  2347. break;
  2348. case CR_DISP_INCOMPLETE:
  2349. case CR_DISP_ERROR:
  2350. case CR_DISP_DENIED:
  2351. case CR_DISP_ISSUED_OUT_OF_BAND: //we consider it a failure in this case
  2352. case CR_DISP_REVOKED:
  2353. default:
  2354. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2355. goto FailureStatusReturn;
  2356. break;
  2357. }
  2358. fResult = TRUE;
  2359. CommonReturn:
  2360. if(bstrCert)
  2361. SysFreeString(bstrCert);
  2362. return fResult;
  2363. FailureStatusReturn:
  2364. //we set the error status for the return message
  2365. //and consider this http transation a success
  2366. pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE;
  2367. pMsgInfo->dwErrorInfo=dwErrorInfo;
  2368. *ppbData=NULL;
  2369. *pcbData=0;
  2370. fResult=TRUE;
  2371. goto CommonReturn;
  2372. ErrorReturn:
  2373. fResult=FALSE;
  2374. goto CommonReturn;
  2375. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2376. TRACE_ERROR(TraceErr);
  2377. }
  2378. //--------------------------------------------------------------------------
  2379. //
  2380. // ProcessCertRequest
  2381. //
  2382. //--------------------------------------------------------------------------
  2383. BOOL ProcessCertRequest( DWORD dwRefreshDays,
  2384. BOOL fPassword,
  2385. PCCERT_CONTEXT pRAEncrypt,
  2386. PCCERT_CONTEXT pRACert,
  2387. CEP_CA_INFO *pCAInfo,
  2388. BYTE *pbRequest,
  2389. DWORD cbRequest,
  2390. BYTE **ppbData,
  2391. DWORD *pcbData,
  2392. CEP_MESSAGE_INFO *pMsgInfo)
  2393. {
  2394. BOOL fResult = FALSE;
  2395. HRESULT hr=E_FAIL;
  2396. DWORD dwFlags=0;
  2397. long dwDisposition=0;
  2398. DWORD dwErrorInfo=MESSAGE_FAILURE_BAD_MESSAGE_CHECK;
  2399. DWORD cbNewRequest=0;
  2400. DWORD cbCert=0;
  2401. BYTE *pbCert=NULL;
  2402. DWORD dwRequestID=0;
  2403. DWORD dwUsage=0;
  2404. LPWSTR pwszTemplate=L"IPSECIntermediateOffline";
  2405. LPWSTR pwszAttr=NULL;
  2406. BSTR bstrRequest=NULL;
  2407. BYTE *pbNewRequest=NULL;
  2408. BSTR bstrCert=NULL;
  2409. BSTR bstrAttr=NULL;
  2410. LPWSTR pwszDNS=NULL;
  2411. CRYPT_DATA_BLOB IPAddress={0, NULL};
  2412. LPWSTR pwszPassword=NULL;
  2413. if(!pCAInfo || !pbRequest || !ppbData || !pcbData || !pMsgInfo)
  2414. goto InvalidArgErr;
  2415. *ppbData=NULL;
  2416. *pcbData=0;
  2417. //check to see if the PKCS10 is in our cached request table
  2418. //if so, we return messages based on the cached requestID
  2419. if(CEPGetCertFromPKCS10(pCAInfo, pbRequest, cbRequest, ppbData, pcbData, pMsgInfo))
  2420. {
  2421. fResult=TRUE;
  2422. }
  2423. else
  2424. {
  2425. //retrieve password and key usage from the request. The presence of password
  2426. //or key usage is not required
  2427. if(!CEPRetrievePasswordFromRequest(pbRequest, cbRequest, &pwszPassword, &dwUsage))
  2428. {
  2429. LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_KEY_USAGE, 1, g_pwszComputerName);
  2430. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2431. goto FailureStatusReturn;
  2432. }
  2433. if(0 == dwUsage)
  2434. {
  2435. LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_KEY_USAGE, 1, g_pwszComputerName);
  2436. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2437. goto FailureStatusReturn;
  2438. }
  2439. //if the password is required, we need to make sure the password
  2440. //supplied is valid.
  2441. if(fPassword)
  2442. {
  2443. if(NULL == pwszPassword)
  2444. {
  2445. LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_PASSWORD, 1, g_pwszComputerName);
  2446. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2447. goto FailureStatusReturn;
  2448. }
  2449. if(!CEPVerifyPasswordAndDeleteFromTable(pwszPassword, dwUsage))
  2450. {
  2451. LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_INVALID_PASSWORD, 1, g_pwszComputerName);
  2452. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2453. goto FailureStatusReturn;
  2454. }
  2455. }
  2456. //if the altname extention is not in the PKCS10, we need to add it
  2457. //otherwise, just use the PKCS10
  2458. dwFlags = CR_IN_PKCS10;
  2459. pbNewRequest=pbRequest;
  2460. cbNewRequest=cbRequest;
  2461. if(!AltNameExist(pbRequest, cbRequest))
  2462. {
  2463. if(GetAltNameElement(pbRequest, cbRequest, &pwszDNS, &IPAddress))
  2464. {
  2465. if(!AddAltNameInRequest(pRACert, pbRequest, cbRequest, pwszDNS, &IPAddress, &pbNewRequest, &cbNewRequest))
  2466. {
  2467. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_FAIL_ADD_ALT, 1, g_pwszComputerName);
  2468. goto TraceErr;
  2469. }
  2470. dwFlags = CR_IN_PKCS7;
  2471. }
  2472. }
  2473. //we always want to make a PKCS7 request so that we can work with enterprise CA
  2474. if(CR_IN_PKCS10 == dwFlags)
  2475. {
  2476. if(!MakePKCS7Request(pRACert, pbRequest, cbRequest, &pbNewRequest, &cbNewRequest))
  2477. goto TraceErr;
  2478. dwFlags = CR_IN_PKCS7;
  2479. }
  2480. if(!(bstrRequest=SysAllocStringByteLen((LPCSTR)pbNewRequest, cbNewRequest)))
  2481. goto MemoryErr;
  2482. //we are requesting a IPSEC offline cert template for Standalone CA
  2483. //or general purpose enterprise CA
  2484. if((FALSE == pCAInfo->fEnterpriseCA) ||
  2485. ((dwUsage & CEP_REQUEST_SIGNATURE) && (dwUsage & CEP_REQUEST_EXCHANGE))
  2486. )
  2487. {
  2488. if(!(bstrAttr=SysAllocString(L"CertificateTemplate:IPSECIntermediateOffline\r\n")))
  2489. goto MemoryErr;
  2490. }
  2491. else
  2492. {
  2493. if(dwUsage & CEP_REQUEST_SIGNATURE)
  2494. {
  2495. if(pCAInfo->pwszTemplateSig)
  2496. pwszTemplate=pCAInfo->pwszTemplateSig;
  2497. }
  2498. else
  2499. {
  2500. //the encryption usage must be set
  2501. if( 0 == (dwUsage & CEP_REQUEST_EXCHANGE))
  2502. {
  2503. LogSCEPEvent(0, FALSE, S_OK, EVENT_MSCEP_NO_KEY_USAGE, 1, g_pwszComputerName);
  2504. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2505. goto FailureStatusReturn;
  2506. }
  2507. if(pCAInfo->pwszTemplateEnt)
  2508. pwszTemplate=pCAInfo->pwszTemplateEnt;
  2509. }
  2510. pwszAttr=(LPWSTR)malloc((wcslen(CEP_TEMPLATE_ATTR) + wcslen(pwszTemplate) + 5) * sizeof(WCHAR));
  2511. if(NULL == pwszAttr)
  2512. goto MemoryErr;
  2513. wcscpy(pwszAttr, CEP_TEMPLATE_ATTR);
  2514. wcscat(pwszAttr, pwszTemplate);
  2515. wcscat(pwszAttr, L"\r\n");
  2516. if(!(bstrAttr=SysAllocString(pwszAttr)))
  2517. goto MemoryErr;
  2518. }
  2519. if(S_OK != (hr=pCAInfo->pICertRequest->Submit(
  2520. CR_IN_BINARY | dwFlags,
  2521. bstrRequest,
  2522. bstrAttr,
  2523. pCAInfo->bstrCAConfig,
  2524. &dwDisposition)))
  2525. {
  2526. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_SUBMIT, 1, g_pwszComputerName);
  2527. goto FailureStatusReturn;
  2528. }
  2529. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2530. switch(dwDisposition)
  2531. {
  2532. case CR_DISP_ISSUED:
  2533. if(S_OK != (hr = pCAInfo->pICertRequest->GetCertificate(CR_OUT_BINARY,
  2534. &bstrCert)))
  2535. {
  2536. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_FAIL_QUERY_CERT, 1, g_pwszComputerName);
  2537. goto FailureStatusReturn;
  2538. }
  2539. cbCert = (DWORD)SysStringByteLen(bstrCert);
  2540. pbCert = (BYTE *)bstrCert;
  2541. //package it in an empty PKCS7
  2542. if(!PackageBlobToPKCS7(CEP_CONTEXT_CERT, pbCert, cbCert, ppbData, pcbData))
  2543. goto FailureStatusReturn;
  2544. pMsgInfo->dwStatus=MESSAGE_STATUS_SUCCESS;
  2545. //copy the PKCS10 to the cached request table
  2546. if(S_OK == (hr=pCAInfo->pICertRequest->GetRequestId((long*)(&dwRequestID))))
  2547. {
  2548. CEPCopyRequestAndRequestID(pbRequest, cbRequest, dwRequestID);
  2549. }
  2550. break;
  2551. case CR_DISP_UNDER_SUBMISSION:
  2552. //copy the transactionID/requestID pair
  2553. if(S_OK == (hr=pCAInfo->pICertRequest->GetRequestId((long*)(&dwRequestID))))
  2554. {
  2555. if(!CEPHashAddRequestAndTransaction(dwRefreshDays,
  2556. dwRequestID,
  2557. &(pMsgInfo->TransactionID)))
  2558. {
  2559. LogSCEPEvent(0, TRUE, HRESULT_FROM_WIN32(GetLastError()), EVENT_MSCEP_ADD_ID, 1, g_pwszComputerName);
  2560. goto DatabaseErr;
  2561. }
  2562. //also copy the PKCS10 to the cached request table for retrial cases
  2563. CEPCopyRequestAndRequestID(pbRequest, cbRequest, dwRequestID);
  2564. }
  2565. else
  2566. {
  2567. LogSCEPEvent(0, TRUE, hr, EVENT_MSCEP_GET_REQUEST_ID, 1, g_pwszComputerName);
  2568. }
  2569. pMsgInfo->dwStatus=MESSAGE_STATUS_PENDING;
  2570. break;
  2571. case CR_DISP_INCOMPLETE:
  2572. case CR_DISP_ERROR:
  2573. case CR_DISP_DENIED:
  2574. case CR_DISP_ISSUED_OUT_OF_BAND: //we consider it a failure in this case
  2575. case CR_DISP_REVOKED:
  2576. default:
  2577. dwErrorInfo=MESSAGE_FAILURE_BAD_REQUEST;
  2578. goto FailureStatusReturn;
  2579. break;
  2580. }
  2581. }
  2582. fResult = TRUE;
  2583. CommonReturn:
  2584. if(pwszAttr)
  2585. free(pwszAttr);
  2586. if(pwszPassword)
  2587. free(pwszPassword);
  2588. if(bstrCert)
  2589. SysFreeString(bstrCert);
  2590. if(bstrRequest)
  2591. SysFreeString(bstrRequest);
  2592. if(bstrAttr)
  2593. SysFreeString(bstrAttr);
  2594. if(pwszDNS)
  2595. free(pwszDNS);
  2596. if(IPAddress.pbData)
  2597. free(IPAddress.pbData);
  2598. if(dwFlags == CR_IN_PKCS7)
  2599. {
  2600. if(pbNewRequest)
  2601. free(pbNewRequest);
  2602. }
  2603. return fResult;
  2604. FailureStatusReturn:
  2605. //we set the error status for the return message
  2606. //and consider this http transation a success
  2607. pMsgInfo->dwStatus=MESSAGE_STATUS_FAILURE;
  2608. pMsgInfo->dwErrorInfo=dwErrorInfo;
  2609. *ppbData=NULL;
  2610. *pcbData=0;
  2611. fResult=TRUE;
  2612. goto CommonReturn;
  2613. ErrorReturn:
  2614. fResult=FALSE;
  2615. goto CommonReturn;
  2616. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2617. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2618. TRACE_ERROR(TraceErr);
  2619. TRACE_ERROR(DatabaseErr);
  2620. }
  2621. //--------------------------------------------------------------------------
  2622. //
  2623. // DecryptMsg
  2624. //
  2625. //--------------------------------------------------------------------------
  2626. BOOL WINAPI DecryptMsg(CEP_RA_INFO *pRAInfo,
  2627. BYTE *pbReqEnv,
  2628. DWORD cbReqEnv,
  2629. BYTE **ppbReqDecrypt,
  2630. DWORD *pcbReqDecrypt)
  2631. {
  2632. BOOL fResult = FALSE;
  2633. CMSG_CTRL_DECRYPT_PARA DecryptPara;
  2634. BOOL fProvFree=FALSE;
  2635. HCRYPTMSG hMsg=NULL;
  2636. if(!pRAInfo || !pbReqEnv || !ppbReqDecrypt || !pcbReqDecrypt)
  2637. goto InvalidArgErr;
  2638. *ppbReqDecrypt=NULL;
  2639. *pcbReqDecrypt=0;
  2640. if(NULL == (hMsg=CryptMsgOpenToDecode(
  2641. ENCODE_TYPE,
  2642. 0,
  2643. 0,
  2644. NULL,
  2645. NULL,
  2646. NULL)))
  2647. goto TraceErr;
  2648. if(!CryptMsgUpdate(hMsg,
  2649. pbReqEnv,
  2650. cbReqEnv,
  2651. TRUE))
  2652. goto TraceErr;
  2653. //decrypt
  2654. memset(&DecryptPara, 0, sizeof(CMSG_CTRL_DECRYPT_PARA));
  2655. DecryptPara.cbSize=sizeof(CMSG_CTRL_DECRYPT_PARA);
  2656. DecryptPara.dwRecipientIndex=0;
  2657. DecryptPara.hCryptProv=pRAInfo->hRAProv;
  2658. DecryptPara.dwKeySpec=pRAInfo->dwKeySpec;
  2659. if(!CryptMsgControl(hMsg,
  2660. 0,
  2661. CMSG_CTRL_DECRYPT,
  2662. &DecryptPara))
  2663. goto TraceErr;
  2664. //get the content
  2665. if(!CryptMsgGetParam(hMsg,
  2666. CMSG_CONTENT_PARAM,
  2667. 0,
  2668. NULL,
  2669. pcbReqDecrypt))
  2670. goto TraceErr;
  2671. *ppbReqDecrypt=(BYTE *)malloc(*pcbReqDecrypt);
  2672. if(NULL==(*ppbReqDecrypt))
  2673. goto MemoryErr;
  2674. if(!CryptMsgGetParam(hMsg,
  2675. CMSG_CONTENT_PARAM,
  2676. 0,
  2677. *ppbReqDecrypt,
  2678. pcbReqDecrypt))
  2679. goto TraceErr;
  2680. fResult = TRUE;
  2681. CommonReturn:
  2682. if(hMsg)
  2683. CryptMsgClose(hMsg);
  2684. return fResult;
  2685. ErrorReturn:
  2686. if(ppbReqDecrypt)
  2687. {
  2688. if(*ppbReqDecrypt)
  2689. {
  2690. free(*ppbReqDecrypt);
  2691. *ppbReqDecrypt=NULL;
  2692. }
  2693. }
  2694. if(pcbReqDecrypt)
  2695. *pcbReqDecrypt=0;
  2696. fResult=FALSE;
  2697. goto CommonReturn;
  2698. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2699. TRACE_ERROR(TraceErr);
  2700. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2701. }
  2702. //--------------------------------------------------------------------------
  2703. //
  2704. // GetContentFromPKCS7
  2705. //
  2706. //--------------------------------------------------------------------------
  2707. BOOL WINAPI GetContentFromPKCS7(BYTE *pbMessage,
  2708. DWORD cbMessage,
  2709. BYTE **ppbContent,
  2710. DWORD *pcbContent,
  2711. CEP_MESSAGE_INFO *pMsgInfo)
  2712. {
  2713. BOOL fResult = FALSE;
  2714. DWORD cbAuth=0;
  2715. DWORD dwIndex=0;
  2716. CRYPT_ATTRIBUTE *pOneAuth=NULL;
  2717. DWORD cb=0;
  2718. DWORD cbCertInfo=0;
  2719. PCCERT_CONTEXT pCertPre=NULL;
  2720. HCRYPTMSG hMsg=NULL;
  2721. CRYPT_ATTRIBUTES *pbAuth=NULL;
  2722. void *pb=NULL;
  2723. CERT_INFO *pbCertInfo=NULL;
  2724. HCERTSTORE hCertStore=NULL;
  2725. PCCERT_CONTEXT pCertCur=NULL;
  2726. if(!pMsgInfo || !ppbContent || !pcbContent)
  2727. goto InvalidArgErr;
  2728. *ppbContent=NULL;
  2729. *pcbContent=0;
  2730. memset(pMsgInfo, 0, sizeof(CEP_MESSAGE_INFO));
  2731. if(NULL == (hMsg=CryptMsgOpenToDecode(
  2732. ENCODE_TYPE,
  2733. 0,
  2734. 0,
  2735. NULL,
  2736. NULL,
  2737. NULL)))
  2738. goto TraceErr;
  2739. if(!CryptMsgUpdate(hMsg,
  2740. pbMessage,
  2741. cbMessage,
  2742. TRUE))
  2743. goto TraceErr;
  2744. //get the content
  2745. if(!CryptMsgGetParam(hMsg,
  2746. CMSG_CONTENT_PARAM,
  2747. 0,
  2748. NULL,
  2749. pcbContent))
  2750. goto TraceErr;
  2751. *ppbContent=(BYTE *)malloc(*pcbContent);
  2752. if(NULL==(*ppbContent))
  2753. goto MemoryErr;
  2754. if(!CryptMsgGetParam(hMsg,
  2755. CMSG_CONTENT_PARAM,
  2756. 0,
  2757. *ppbContent,
  2758. pcbContent))
  2759. goto TraceErr;
  2760. //get message type
  2761. if(!CryptMsgGetParam(hMsg,
  2762. CMSG_SIGNER_AUTH_ATTR_PARAM,
  2763. 0,
  2764. NULL,
  2765. &cbAuth))
  2766. goto TraceErr;
  2767. pbAuth=(CRYPT_ATTRIBUTES *)malloc(cbAuth);
  2768. if(NULL==pbAuth)
  2769. goto MemoryErr;
  2770. if(!CryptMsgGetParam(hMsg,
  2771. CMSG_SIGNER_AUTH_ATTR_PARAM,
  2772. 0,
  2773. pbAuth,
  2774. &cbAuth))
  2775. goto TraceErr;
  2776. for(dwIndex=0; dwIndex < pbAuth->cAttr; dwIndex++)
  2777. {
  2778. pOneAuth=&(pbAuth->rgAttr[dwIndex]);
  2779. if((!(pOneAuth->pszObjId)) || (!(pOneAuth->rgValue)))
  2780. continue;
  2781. if((0==(pOneAuth->rgValue[0].cbData)) || (!(pOneAuth->rgValue[0].pbData)))
  2782. continue;
  2783. if(0 == strcmp(pOneAuth->pszObjId, szOIDVerisign_MessageType))
  2784. {
  2785. if(!CEPAllocAndDecode(X509_ANY_STRING,
  2786. pOneAuth->rgValue[0].pbData,
  2787. pOneAuth->rgValue[0].cbData,
  2788. (void **)&pb,
  2789. &cb))
  2790. goto TraceErr;
  2791. if(CERT_RDN_PRINTABLE_STRING != ((CERT_NAME_VALUE *)pb)->dwValueType)
  2792. goto InvalidArgErr;
  2793. pMsgInfo->dwMessageType = atol((LPSTR)(((CERT_NAME_VALUE *)pb)->Value.pbData));
  2794. }
  2795. else
  2796. {
  2797. if(0 == strcmp(pOneAuth->pszObjId, szOIDVerisign_SenderNonce))
  2798. {
  2799. if(!CEPAllocAndDecode(X509_OCTET_STRING,
  2800. pOneAuth->rgValue[0].pbData,
  2801. pOneAuth->rgValue[0].cbData,
  2802. (void **)&pb,
  2803. &cb))
  2804. goto TraceErr;
  2805. //the SenderNonce in the request is the recipienNonce in the response
  2806. if(!AllocAndCopyBlob(&(pMsgInfo->RecipientNonce),
  2807. (CERT_BLOB *)pb))
  2808. goto TraceErr;
  2809. }
  2810. else
  2811. {
  2812. if(0 == strcmp(pOneAuth->pszObjId, szOIDVerisign_TransactionID))
  2813. {
  2814. if(!CEPAllocAndDecode(X509_ANY_STRING,
  2815. pOneAuth->rgValue[0].pbData,
  2816. pOneAuth->rgValue[0].cbData,
  2817. (void **)&pb,
  2818. &cb))
  2819. goto TraceErr;
  2820. if(CERT_RDN_PRINTABLE_STRING != ((CERT_NAME_VALUE *)pb)->dwValueType)
  2821. goto InvalidArgErr;
  2822. if(!AllocAndCopyString(&(pMsgInfo->TransactionID),
  2823. (LPSTR)(((CERT_NAME_VALUE *)pb)->Value.pbData)))
  2824. goto TraceErr;
  2825. }
  2826. }
  2827. }
  2828. if(pb)
  2829. free(pb);
  2830. pb=NULL;
  2831. cb=0;
  2832. }
  2833. //we have to have TrasanctionID and messageType
  2834. if((0 == pMsgInfo->dwMessageType)||(NULL == (pMsgInfo->TransactionID.pbData)))
  2835. goto InvalidArgErr;
  2836. //we get the serial number of the signing certificate
  2837. cbCertInfo=0;
  2838. if(!CryptMsgGetParam(hMsg,
  2839. CMSG_SIGNER_CERT_INFO_PARAM,
  2840. 0,
  2841. NULL,
  2842. &cbCertInfo))
  2843. goto TraceErr;
  2844. pbCertInfo=(CERT_INFO *)malloc(cbCertInfo);
  2845. if(NULL==pbCertInfo)
  2846. goto MemoryErr;
  2847. if(!CryptMsgGetParam(hMsg,
  2848. CMSG_SIGNER_CERT_INFO_PARAM,
  2849. 0,
  2850. pbCertInfo,
  2851. &cbCertInfo))
  2852. goto TraceErr;
  2853. if(!AllocAndCopyBlob(&(pMsgInfo->SerialNumber), (CERT_BLOB *)(&(pbCertInfo->SerialNumber))))
  2854. goto TraceErr;
  2855. //we get the rounter's CA issued certificate for GetCertInitial message
  2856. if((MESSAGE_TYPE_GET_CERT_INITIAL == pMsgInfo->dwMessageType) ||
  2857. (MESSAGE_TYPE_CERT_REQUEST == pMsgInfo->dwMessageType) ||
  2858. (MESSAGE_TYPE_GET_CERT == pMsgInfo->dwMessageType)
  2859. )
  2860. {
  2861. if(NULL == (hCertStore=CertOpenStore(CERT_STORE_PROV_MSG,
  2862. ENCODE_TYPE,
  2863. NULL,
  2864. 0,
  2865. hMsg)))
  2866. goto TraceErr;
  2867. pCertPre=NULL;
  2868. while(pCertCur=CertEnumCertificatesInStore(hCertStore, pCertPre))
  2869. {
  2870. if(SameCert(pCertCur->pCertInfo, pbCertInfo))
  2871. {
  2872. if(NULL==(pMsgInfo->pSigningCert=CertDuplicateCertificateContext(pCertCur)))
  2873. goto TraceErr;
  2874. break;
  2875. }
  2876. pCertPre=pCertCur;
  2877. }
  2878. if(NULL == (pMsgInfo->pSigningCert))
  2879. goto InvalidArgErr;
  2880. }
  2881. fResult = TRUE;
  2882. CommonReturn:
  2883. if(pCertCur)
  2884. CertFreeCertificateContext(pCertCur);
  2885. if(hCertStore)
  2886. CertCloseStore(hCertStore, 0);
  2887. if(pbCertInfo)
  2888. free(pbCertInfo);
  2889. if(pb)
  2890. free(pb);
  2891. if(pbAuth)
  2892. free(pbAuth);
  2893. if(hMsg)
  2894. CryptMsgClose(hMsg);
  2895. return fResult;
  2896. ErrorReturn:
  2897. if(ppbContent)
  2898. {
  2899. if(*ppbContent)
  2900. {
  2901. free(*ppbContent);
  2902. *ppbContent=NULL;
  2903. }
  2904. }
  2905. if(pcbContent)
  2906. *pcbContent=0;
  2907. FreeMessageInfo(pMsgInfo);
  2908. fResult=FALSE;
  2909. goto CommonReturn;
  2910. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2911. TRACE_ERROR(TraceErr);
  2912. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2913. }
  2914. //--------------------------------------------------------------------------
  2915. //
  2916. // SameCert
  2917. //
  2918. //--------------------------------------------------------------------------
  2919. BOOL WINAPI SameCert(CERT_INFO *pCertInfoOne, CERT_INFO *pCertInfoTwo)
  2920. {
  2921. if(!pCertInfoOne || !pCertInfoTwo)
  2922. return FALSE;
  2923. if(!SameBlob(&(pCertInfoOne->SerialNumber), &(pCertInfoTwo->SerialNumber)))
  2924. return FALSE;
  2925. if(!SameBlob((CRYPT_INTEGER_BLOB *)(&(pCertInfoOne->Issuer)),
  2926. (CRYPT_INTEGER_BLOB *)(&(pCertInfoTwo->Issuer))))
  2927. return FALSE;
  2928. return TRUE;
  2929. }
  2930. //--------------------------------------------------------------------------
  2931. //
  2932. // SameBlob
  2933. //
  2934. //--------------------------------------------------------------------------
  2935. BOOL WINAPI SameBlob(CRYPT_INTEGER_BLOB *pBlobOne, CRYPT_INTEGER_BLOB *pBlobTwo)
  2936. {
  2937. if(!pBlobOne || !pBlobTwo)
  2938. return FALSE;
  2939. if(pBlobOne->cbData != pBlobTwo->cbData)
  2940. return FALSE;
  2941. if(0!=(memcmp(pBlobOne->pbData, pBlobTwo->pbData,pBlobTwo->cbData)))
  2942. return FALSE;
  2943. return TRUE;
  2944. }
  2945. //--------------------------------------------------------------------------
  2946. //
  2947. // CEPAllocAndDecode
  2948. //
  2949. //--------------------------------------------------------------------------
  2950. BOOL WINAPI CEPAllocAndDecode( LPCSTR lpszStructType,
  2951. BYTE *pbEncoded,
  2952. DWORD cbEncoded,
  2953. void **ppb,
  2954. DWORD *pcb)
  2955. {
  2956. BOOL fResult = FALSE;
  2957. *pcb=0;
  2958. *ppb=NULL;
  2959. if(!CryptDecodeObject(ENCODE_TYPE,
  2960. lpszStructType,
  2961. pbEncoded,
  2962. cbEncoded,
  2963. 0,
  2964. NULL,
  2965. pcb))
  2966. goto DecodeErr;
  2967. *ppb=malloc(*pcb);
  2968. if(NULL==(*ppb))
  2969. goto MemoryErr;
  2970. if(!CryptDecodeObject(ENCODE_TYPE,
  2971. lpszStructType,
  2972. pbEncoded,
  2973. cbEncoded,
  2974. 0,
  2975. *ppb,
  2976. pcb))
  2977. goto DecodeErr;
  2978. fResult = TRUE;
  2979. CommonReturn:
  2980. return fResult;
  2981. ErrorReturn:
  2982. if(ppb)
  2983. {
  2984. if(*ppb)
  2985. {
  2986. free(*ppb);
  2987. *ppb=NULL;
  2988. }
  2989. }
  2990. if(pcb)
  2991. *pcb=0;
  2992. fResult=FALSE;
  2993. goto CommonReturn;
  2994. TRACE_ERROR(DecodeErr);
  2995. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2996. }
  2997. //--------------------------------------------------------------------------
  2998. //
  2999. // FreeMessageInfo
  3000. //
  3001. //--------------------------------------------------------------------------
  3002. void WINAPI FreeMessageInfo(CEP_MESSAGE_INFO *pMsgInfo)
  3003. {
  3004. if(pMsgInfo)
  3005. {
  3006. if(pMsgInfo->TransactionID.pbData)
  3007. free(pMsgInfo->TransactionID.pbData);
  3008. if(pMsgInfo->SenderNonce.pbData)
  3009. free(pMsgInfo->SenderNonce.pbData);
  3010. if(pMsgInfo->RecipientNonce.pbData)
  3011. free(pMsgInfo->RecipientNonce.pbData);
  3012. if(pMsgInfo->SerialNumber.pbData)
  3013. free(pMsgInfo->SerialNumber.pbData);
  3014. if(pMsgInfo->pSigningCert)
  3015. CertFreeCertificateContext(pMsgInfo->pSigningCert);
  3016. memset(pMsgInfo, 0, sizeof(CEP_MESSAGE_INFO));
  3017. }
  3018. }
  3019. //--------------------------------------------------------------------------
  3020. //
  3021. // AllocAndCopyBlob
  3022. //
  3023. //--------------------------------------------------------------------------
  3024. BOOL WINAPI AllocAndCopyBlob(CERT_BLOB *pDestBlob,
  3025. CERT_BLOB *pSrcBlob)
  3026. {
  3027. memset(pDestBlob, 0, sizeof(CERT_BLOB));
  3028. if(NULL==pSrcBlob->pbData)
  3029. {
  3030. SetLastError(E_INVALIDARG);
  3031. return FALSE;
  3032. }
  3033. pDestBlob->pbData = (BYTE *)malloc(pSrcBlob->cbData);
  3034. if(NULL==(pDestBlob->pbData))
  3035. {
  3036. SetLastError(E_OUTOFMEMORY);
  3037. return FALSE;
  3038. }
  3039. pDestBlob->cbData=pSrcBlob->cbData;
  3040. memcpy(pDestBlob->pbData, pSrcBlob->pbData, pDestBlob->cbData);
  3041. return TRUE;
  3042. }
  3043. //--------------------------------------------------------------------------
  3044. //
  3045. // AllocAndCopyString
  3046. //
  3047. //--------------------------------------------------------------------------
  3048. BOOL WINAPI AllocAndCopyString(CERT_BLOB *pDestBlob,
  3049. LPSTR psz)
  3050. {
  3051. if(!psz)
  3052. {
  3053. SetLastError(E_INVALIDARG);
  3054. return FALSE;
  3055. }
  3056. pDestBlob->cbData=0;
  3057. pDestBlob->pbData=NULL;
  3058. pDestBlob->pbData=(BYTE*)malloc(strlen(psz) + 1);
  3059. if(NULL == pDestBlob->pbData)
  3060. {
  3061. SetLastError(E_OUTOFMEMORY);
  3062. return FALSE;
  3063. }
  3064. pDestBlob->cbData=strlen(psz);
  3065. strcpy((LPSTR)pDestBlob->pbData, psz);
  3066. return TRUE;
  3067. }
  3068. //--------------------------------------------------------------------------
  3069. //
  3070. // GetTagValue
  3071. //
  3072. //--------------------------------------------------------------------------
  3073. LPSTR GetTagValue(LPSTR szString, LPSTR szTag)
  3074. {
  3075. LPSTR pszValue=NULL;
  3076. DWORD cbString=0;
  3077. DWORD cbTag=0;
  3078. cbString = strlen(szString);
  3079. cbTag = strlen(szTag);
  3080. for(pszValue=szString; cbString > cbTag; pszValue++, cbString--)
  3081. {
  3082. if((*pszValue) == (*szTag))
  3083. {
  3084. if(0==_strnicmp(pszValue, szTag, cbTag))
  3085. {
  3086. //skip the tag
  3087. pszValue += cbTag * sizeof(CHAR);
  3088. return pszValue;
  3089. }
  3090. }
  3091. }
  3092. return NULL;
  3093. }