Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1312 lines
33 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: SIPObjCB.cpp (CAB)
  8. //
  9. // Contents: Microsoft SIP Provider
  10. //
  11. // History: 15-Feb-1997 pberkman created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "global.hxx"
  15. #include "sipobjcb.hxx"
  16. #include "sha.h"
  17. #include "md5.h"
  18. ////////////////////////////////////////////////////////////////////////////
  19. //
  20. // construct/destruct:
  21. //
  22. SIPObjectCAB_::SIPObjectCAB_(DWORD id) : SIPObject_(id)
  23. {
  24. memset(&Para, 0x00, sizeof(CAB_PARA));
  25. fUseV1Sig = FALSE;
  26. }
  27. SIPObjectCAB_::~SIPObjectCAB_(void)
  28. {
  29. FreeHeader();
  30. }
  31. ////////////////////////////////////////////////////////////////////////////
  32. //
  33. // public:
  34. //
  35. BOOL SIPObjectCAB_::RemoveSignedDataMsg(SIP_SUBJECTINFO *pSI,DWORD dwIdx)
  36. {
  37. if (this->FileHandleFromSubject(pSI, GENERIC_READ | GENERIC_WRITE))
  38. {
  39. return(this->RemoveCertificate(dwIdx));
  40. }
  41. return(FALSE);
  42. }
  43. BOOL SIPObjectCAB_::CreateIndirectData(SIP_SUBJECTINFO *pSI,DWORD *pdwDLen,
  44. SIP_INDIRECT_DATA *psData)
  45. {
  46. BOOL fRet;
  47. BYTE *pbDigest;
  48. BYTE *pbAttrData;
  49. SPC_LINK SpcLink;
  50. DWORD cbDigest;
  51. HCRYPTPROV hProvT;
  52. pbDigest = NULL;
  53. pbAttrData = NULL;
  54. fRet = TRUE;
  55. hProvT = pSI->hProv;
  56. if (!(hProvT))
  57. {
  58. if (!(this->LoadDefaultProvider()))
  59. {
  60. goto GetProviderFailed;
  61. }
  62. hProvT = this->hProv;
  63. }
  64. memset(&SpcLink,0x00,sizeof(SPC_LINK));
  65. SpcLink.dwLinkChoice = SPC_FILE_LINK_CHOICE;
  66. SpcLink.pwszFile = OBSOLETE_TEXT_W;
  67. if (!(psData))
  68. {
  69. HCRYPTHASH hHash;
  70. DWORD dwRetLen;
  71. DWORD dwEncLen;
  72. DWORD dwAlgId;
  73. dwRetLen = sizeof(SIP_INDIRECT_DATA);
  74. // crypt_algorithm_identifier...
  75. // obj id
  76. dwRetLen += strlen(pSI->DigestAlgorithm.pszObjId);
  77. dwRetLen += 1; // null term.
  78. // parameters (none)...
  79. // crypt_attribute_type_value size...
  80. dwRetLen += strlen(this->GetDataObjectID());
  81. dwRetLen += 1; // null term.
  82. // size of the value
  83. dwEncLen = 0;
  84. CryptEncodeObject( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  85. this->GetDataOIDHint(),
  86. &SpcLink,
  87. NULL,
  88. &dwEncLen);
  89. if (dwEncLen < 1)
  90. {
  91. goto EncodeError;
  92. }
  93. dwRetLen += dwEncLen;
  94. if ((dwAlgId = CertOIDToAlgId(pSI->DigestAlgorithm.pszObjId)) == 0)
  95. {
  96. goto BadAlgId;
  97. }
  98. switch (dwAlgId)
  99. {
  100. case CALG_MD5:
  101. cbDigest = MD5DIGESTLEN;
  102. break;
  103. case CALG_SHA1:
  104. cbDigest = A_SHA_DIGEST_LEN;
  105. break;
  106. default:
  107. if (!(CryptCreateHash(hProvT, dwAlgId, NULL, 0, &hHash)))
  108. {
  109. goto CreateHashFailed;
  110. }
  111. // just to get hash length
  112. if (!(CryptHashData(hHash,(const BYTE *)" ",1,0)))
  113. {
  114. CryptDestroyHash(hHash);
  115. goto HashDataFailed;
  116. }
  117. cbDigest = 0;
  118. CryptGetHashParam(hHash, HP_HASHVAL, NULL, &cbDigest,0);
  119. CryptDestroyHash(hHash);
  120. }
  121. dwRetLen += cbDigest;
  122. *pdwDLen = dwRetLen;
  123. goto CommonReturn;
  124. }
  125. if (!(this->FileHandleFromSubject(pSI, (pSI->dwFlags & MSSIP_FLAGS_PROHIBIT_RESIZE_ON_CREATE) ?
  126. GENERIC_READ : (GENERIC_READ | GENERIC_WRITE))))
  127. {
  128. goto SubjectFileFailure;
  129. }
  130. //
  131. // version 1 had the signature in the header. We want
  132. // the signature at the end and our structure in the
  133. // header where the signature used to be. -- check it.
  134. //
  135. if (!(pSI->dwFlags & MSSIP_FLAGS_PROHIBIT_RESIZE_ON_CREATE))
  136. {
  137. if (!(this->ReadHeader()))
  138. {
  139. goto ReadHeaderFailed;
  140. }
  141. if (!(this->ReserveSignedData(sizeof(CABSignatureStruct_))))
  142. {
  143. goto ReserveDataFailed;
  144. }
  145. if (!(this->MapFile()))
  146. {
  147. goto MapFileFailed;
  148. }
  149. }
  150. if (!(pbDigest = this->DigestFile(hProvT, 0, pSI->DigestAlgorithm.pszObjId, &cbDigest)))
  151. {
  152. goto DigestFileFailed;
  153. }
  154. DWORD_PTR dwOffset;
  155. DWORD dwRetLen;
  156. dwRetLen = 0;
  157. CryptEncodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, this->GetDataOIDHint(), &SpcLink,
  158. NULL, &dwRetLen);
  159. if (dwRetLen < 1)
  160. {
  161. goto EncodeError;
  162. }
  163. if (!(pbAttrData = (BYTE *)this->SIPNew(dwRetLen)))
  164. {
  165. goto MemoryError;
  166. }
  167. if (!(CryptEncodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, this->GetDataOIDHint(), &SpcLink,
  168. pbAttrData, &dwRetLen)))
  169. {
  170. goto EncodeError;
  171. }
  172. dwOffset = (DWORD_PTR)psData + sizeof(SIP_INDIRECT_DATA);
  173. strcpy((char *)dwOffset, this->GetDataObjectID());
  174. psData->Data.pszObjId = (LPSTR)dwOffset;
  175. dwOffset += (strlen(SPC_LINK_OBJID) + 1);
  176. memcpy((void *)dwOffset, pbAttrData,dwRetLen);
  177. psData->Data.Value.pbData = (BYTE *)dwOffset;
  178. psData->Data.Value.cbData = dwRetLen;
  179. dwOffset += dwRetLen;
  180. strcpy((char *)dwOffset, (char *)pSI->DigestAlgorithm.pszObjId);
  181. psData->DigestAlgorithm.pszObjId = (char *)dwOffset;
  182. psData->DigestAlgorithm.Parameters.cbData = 0;
  183. psData->DigestAlgorithm.Parameters.pbData = NULL;
  184. dwOffset += (strlen(pSI->DigestAlgorithm.pszObjId) + 1);
  185. memcpy((void *)dwOffset,pbDigest,cbDigest);
  186. psData->Digest.pbData = (BYTE *)dwOffset;
  187. psData->Digest.cbData = cbDigest;
  188. CommonReturn:
  189. if (pbDigest)
  190. {
  191. delete pbDigest;
  192. }
  193. if (pbAttrData)
  194. {
  195. delete pbAttrData;
  196. }
  197. return(fRet);
  198. ErrorReturn:
  199. fRet = FALSE;
  200. goto CommonReturn;
  201. TRACE_ERROR_EX(DBG_SS, EncodeError);
  202. TRACE_ERROR_EX(DBG_SS, SubjectFileFailure);
  203. TRACE_ERROR_EX(DBG_SS, HashDataFailed);
  204. TRACE_ERROR_EX(DBG_SS, CreateHashFailed);
  205. TRACE_ERROR_EX(DBG_SS, ReadHeaderFailed);
  206. TRACE_ERROR_EX(DBG_SS, ReserveDataFailed);
  207. TRACE_ERROR_EX(DBG_SS, MapFileFailed);
  208. TRACE_ERROR_EX(DBG_SS, DigestFileFailed);
  209. TRACE_ERROR_EX(DBG_SS, GetProviderFailed);
  210. SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY);
  211. SET_ERROR_VAR_EX(DBG_SS, BadAlgId, NTE_BAD_ALGID);
  212. }
  213. ////////////////////////////////////////////////////////////////////////////
  214. //
  215. // protected:
  216. //
  217. BOOL SIPObjectCAB_::GetMessageFromFile(SIP_SUBJECTINFO *pSI,
  218. WIN_CERTIFICATE *pWinCert,
  219. DWORD dwIndex,DWORD *pcbCert)
  220. {
  221. DWORD cbCert;
  222. if (dwIndex != 0)
  223. {
  224. goto InvalidParam;
  225. }
  226. if (!(this->ReadHeader()))
  227. {
  228. goto ReadHeaderFailed;
  229. }
  230. if (Para.Hdr.cbSig == 0)
  231. {
  232. goto NoSignature;
  233. }
  234. if (!(fUseV1Sig))
  235. {
  236. //
  237. // Version 2 header
  238. //
  239. cbCert = OFFSETOF(WIN_CERTIFICATE, bCertificate) +
  240. Para.Hdr.pCabSigStruct->cbSig;
  241. if (*pcbCert < cbCert)
  242. {
  243. *pcbCert = cbCert;
  244. goto BufferTooSmall;
  245. }
  246. if (pWinCert)
  247. {
  248. if (!(this->ReadSignedData(pWinCert->bCertificate)))
  249. {
  250. goto ReadSignedFailed;
  251. }
  252. }
  253. }
  254. else
  255. {
  256. //
  257. // Version 1 header
  258. //
  259. cbCert = OFFSETOF(WIN_CERTIFICATE, bCertificate) + Para.Hdr.cbSig;
  260. if (*pcbCert < cbCert)
  261. {
  262. *pcbCert = cbCert;
  263. goto BufferTooSmall;
  264. }
  265. if (pWinCert)
  266. {
  267. BYTE *pbSignedData;
  268. pbSignedData = Para.Hdr.pbReserve + RESERVE_CNT_HDR_LEN + Para.Hdr.cbJunk;
  269. pWinCert->wRevision = WIN_CERT_REVISION_1_0;
  270. memcpy(pWinCert->bCertificate, pbSignedData, Para.Hdr.cbSig);
  271. }
  272. }
  273. pWinCert->dwLength = cbCert;
  274. pWinCert->wCertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
  275. return(TRUE);
  276. ErrorReturn:
  277. return(FALSE);
  278. TRACE_ERROR_EX(DBG_SS, ReadHeaderFailed);
  279. TRACE_ERROR_EX(DBG_SS, ReadSignedFailed);
  280. SET_ERROR_VAR_EX(DBG_SS, InvalidParam, ERROR_INVALID_PARAMETER);
  281. SET_ERROR_VAR_EX(DBG_SS, BufferTooSmall,ERROR_INSUFFICIENT_BUFFER);
  282. SET_ERROR_VAR_EX(DBG_SS, NoSignature, TRUST_E_NOSIGNATURE);
  283. }
  284. BOOL SIPObjectCAB_::PutMessageInFile(SIP_SUBJECTINFO *pSI,
  285. WIN_CERTIFICATE *pWinCert,DWORD *pdwIndex)
  286. {
  287. if ((pWinCert->dwLength <= OFFSETOF(WIN_CERTIFICATE,bCertificate)) ||
  288. (pWinCert->wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA))
  289. {
  290. SetLastError((DWORD)ERROR_INVALID_PARAMETER);
  291. return(FALSE);
  292. }
  293. if (this->ReadHeader())
  294. {
  295. if (!(fUseV1Sig))
  296. {
  297. //
  298. // version 2
  299. //
  300. if (this->WriteSignedData((BYTE *)&(pWinCert->bCertificate),
  301. pWinCert->dwLength -
  302. OFFSETOF(WIN_CERTIFICATE, bCertificate)))
  303. {
  304. return(TRUE);
  305. }
  306. }
  307. else
  308. {
  309. //
  310. // version 1
  311. //
  312. DWORD dwCheck;
  313. DWORD cbSignedData;
  314. cbSignedData = pWinCert->dwLength - OFFSETOF(WIN_CERTIFICATE, bCertificate);
  315. dwCheck = RESERVE_LEN_ALIGN(RESERVE_CNT_HDR_LEN + Para.Hdr.cbJunk + cbSignedData) -
  316. Para.Hdr.cfres.cbCFHeader;
  317. if (dwCheck > 0)
  318. {
  319. SetLastError(CRYPT_E_FILERESIZED);
  320. return(FALSE);
  321. }
  322. if (WriteSignedDataV1((PBYTE)&(pWinCert->bCertificate), cbSignedData))
  323. {
  324. return(TRUE);
  325. }
  326. }
  327. }
  328. return(FALSE);
  329. }
  330. BOOL SIPObjectCAB_::GetDigestStream(DIGEST_DATA *pDigestData,
  331. DIGEST_FUNCTION pfnCallBack, DWORD dwFlags)
  332. {
  333. if (dwFlags != 0)
  334. {
  335. goto InvalidParam;
  336. }
  337. if (!(this->ReadHeader()))
  338. {
  339. goto ReadHeaderFailed;
  340. }
  341. if (!(this->DigestHeader(pfnCallBack, pDigestData)))
  342. {
  343. goto DigestFailed;
  344. }
  345. DWORD cbRemain;
  346. cbRemain = this->cbFileMap - Para.Hdr.cbTotalHdr;
  347. if (!(fUseV1Sig) && (Para.Hdr.pCabSigStruct))
  348. {
  349. cbRemain -= Para.Hdr.pCabSigStruct->cbSig;
  350. }
  351. if ((Para.Hdr.cfheader.cbCabinet - Para.Hdr.cbTotalHdr) != cbRemain)
  352. {
  353. goto BadFileFormat;
  354. }
  355. if (this->cbFileMap < (Para.Hdr.cbTotalHdr + cbRemain))
  356. {
  357. goto BadFileFormat;
  358. }
  359. __try {
  360. if (!(pfnCallBack(pDigestData, &this->pbFileMap[Para.Hdr.cbTotalHdr], cbRemain)))
  361. {
  362. goto HashFailed;
  363. }
  364. }
  365. __except(EXCEPTION_EXECUTE_HANDLER) {
  366. SetLastError(GetExceptionCode());
  367. goto HashFailed;
  368. }
  369. return(TRUE);
  370. ErrorReturn:
  371. return(FALSE);
  372. TRACE_ERROR_EX(DBG_SS, DigestFailed);
  373. TRACE_ERROR_EX(DBG_SS, ReadHeaderFailed);
  374. TRACE_ERROR_EX(DBG_SS, HashFailed);
  375. SET_ERROR_VAR_EX(DBG_SS, InvalidParam, ERROR_INVALID_PARAMETER);
  376. SET_ERROR_VAR_EX(DBG_SS, BadFileFormat, ERROR_BAD_FORMAT);
  377. }
  378. ////////////////////////////////////////////////////////////////////////////
  379. //
  380. // private:
  381. //
  382. BOOL SIPObjectCAB_::RemoveCertificate(DWORD Index)
  383. {
  384. return(FALSE); // not yet!!! Currently, we only support 1.
  385. # ifdef _DONT_USE_YET
  386. BYTE *pbFolders;
  387. DWORD cbFolders;
  388. BYTE *pbReserve;
  389. USHORT cbReserve;
  390. if (Index != 0)
  391. {
  392. SetLastError((DWORD)ERROR_INVALID_PARAMETER);
  393. return(FALSE);
  394. }
  395. pbFolders = NULL;
  396. cbFolders = 0;
  397. Para.dwFlags = VERIFY_CAB_FLAG;
  398. if (this->ReadHeader())
  399. {
  400. if (Para.Hdr.cbSig <= (RESERVE_CNT_HDR_LEN + Para.Hdr.cbJunk))
  401. {
  402. SetLastError((DWORD)CRYPT_E_NO_MATCH);
  403. return(FALSE);
  404. }
  405. long lShift;
  406. if (Para.Hdr.cbJunk)
  407. {
  408. lShift = Para.Hdr.cbSig;
  409. if (Para.Hdr.pbReserve)
  410. {
  411. *((USHORT *)Para.Hdr.pbReserve) = Para.Hdr.cbJunk;
  412. *((USHORT *)(Para.Hdr.pbReserve + sizeof(USHORT))) = 0; // no more sig
  413. }
  414. }
  415. else
  416. {
  417. lShift = Para.Hdr.cbSig + (sizeof(USHORT) * 2);
  418. Para.Hdr.cfheader.flags &= ~(cfhdrRESERVE_PRESENT);
  419. if (Para.Hdr.pbReserve)
  420. {
  421. delete Para.Hdr.pbReserve;
  422. Para.Hdr.pbReserve = NULL;
  423. }
  424. }
  425. Para.Hdr.cbSig = 0;
  426. Para.Hdr.cfres.cbCFHeader -= (USHORT)lShift; // subtract the amount we want to shrink.
  427. // adjust the header offsets
  428. if (this->ShiftFileBytes(lShift))
  429. {
  430. Para.Hdr.cbTotalHdr -= lShift;
  431. Para.Hdr.cfheader.cbCabinet -= lShift;
  432. Para.Hdr.cfheader.coffFiles -= lShift;
  433. }
  434. // redo checksums....
  435. this->ChecksumHeader();
  436. if (this->WriteHeader())
  437. {
  438. // We need to read in the folders to adjust their CFDATA file offset
  439. if (Para.Hdr.cfheader.cFolders)
  440. {
  441. if (SetFilePointer(this->hFile,
  442. Para.Hdr.cbTotalHdr + lShift,
  443. NULL, FILE_BEGIN) == 0xFFFFFFFF)
  444. {
  445. return(FALSE);
  446. }
  447. USHORT cFolders;
  448. LONG cbFolder;
  449. cFolders = Para.Hdr.cfheader.cFolders;
  450. cbFolder = sizeof(CFFOLDER) + Para.Hdr.cfres.cbCFFolder;
  451. cbFolders = cbFolder * cFolders;
  452. if (!(pbFolders = (BYTE *)this->SIPNew(cbFolders)))
  453. {
  454. return(FALSE);
  455. }
  456. DWORD cbFile;
  457. if (!(ReadFile(this->hFile, pbFolders, cbFolders, &cbFile, NULL)) ||
  458. (cbFile != cbFolders))
  459. {
  460. delete pbFolders;
  461. SetLastError(ERROR_BAD_FORMAT);
  462. return(FALSE);
  463. }
  464. BYTE *pb;
  465. pb = pbFolders;
  466. while (cFolders > 0)
  467. {
  468. ((CFFOLDER *)pb)->coffCabStart -= lShift;
  469. pb += cbFolder;
  470. cFolders--;
  471. }
  472. // back up and write!
  473. if (SetFilePointer(this->hFile, -((LONG)cbFolders),
  474. NULL, FILE_CURRENT) == 0xFFFFFFFF)
  475. {
  476. delete pbFolders;
  477. return(FALSE);
  478. }
  479. if (!(WriteFile(this->hFile, pbFolders, cbFolders, &cbFile, NULL)) ||
  480. (cbFile != cbFolders))
  481. {
  482. delete pbFolders;
  483. return(FALSE);
  484. }
  485. delete pbFolders;
  486. }
  487. return(TRUE);
  488. }
  489. }
  490. return(FALSE);
  491. # endif // _DONT_USE_YET
  492. }
  493. BOOL SIPObjectCAB_::ReadSignedData(BYTE *pbRet)
  494. {
  495. //
  496. // this function is NOT called for version 1 Sigs!
  497. //
  498. if (Para.Hdr.pCabSigStruct->cbFileOffset != (DWORD)Para.Hdr.cfheader.cbCabinet)
  499. {
  500. SetLastError((DWORD)TRUST_E_NOSIGNATURE);
  501. return(FALSE);
  502. }
  503. if (this->cbFileMap < (Para.Hdr.pCabSigStruct->cbFileOffset +
  504. Para.Hdr.pCabSigStruct->cbSig))
  505. {
  506. SetLastError(ERROR_BAD_FORMAT);
  507. return(FALSE);
  508. }
  509. __try {
  510. memcpy(pbRet, &this->pbFileMap[Para.Hdr.pCabSigStruct->cbFileOffset], Para.Hdr.pCabSigStruct->cbSig);
  511. }
  512. __except(EXCEPTION_EXECUTE_HANDLER) {
  513. SetLastError(GetExceptionCode());
  514. return(FALSE);
  515. }
  516. return(TRUE);
  517. }
  518. BOOL SIPObjectCAB_::WriteSignedData(BYTE *pbSig, DWORD cbSig)
  519. {
  520. //
  521. // this function is NOT called for version 1 Sigs!
  522. //
  523. if (!(pbSig) || (cbSig == 0))
  524. {
  525. return(FALSE);
  526. }
  527. CABSignatureStruct_ sSig;
  528. memset(&sSig, 0x00, sizeof(CABSignatureStruct_));
  529. sSig.cbFileOffset = Para.Hdr.cfheader.cbCabinet;
  530. sSig.cbSig = cbSig;
  531. memcpy(Para.Hdr.pbReserve + RESERVE_CNT_HDR_LEN + Para.Hdr.cbJunk,
  532. &sSig, sizeof(CABSignatureStruct_));
  533. if (!(this->WriteHeader()))
  534. {
  535. return(FALSE);
  536. }
  537. if (SetFilePointer(this->hFile, Para.Hdr.cfheader.cbCabinet, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  538. {
  539. return(FALSE);
  540. }
  541. DWORD cbWritten;
  542. if (!(WriteFile(this->hFile, pbSig, cbSig, &cbWritten, NULL)) ||
  543. (cbWritten != cbSig))
  544. {
  545. return(FALSE);
  546. }
  547. this->UnmapFile();
  548. SetEndOfFile(this->hFile); // signature is the LAST thing!!!
  549. return(this->MapFile());
  550. }
  551. BOOL SIPObjectCAB_::WriteSignedDataV1(BYTE *pbSignedData, DWORD cbSignedData)
  552. {
  553. if (!(pbSignedData) || (cbSignedData == 0))
  554. {
  555. return(FALSE);
  556. }
  557. memcpy(Para.Hdr.pbReserve + RESERVE_CNT_HDR_LEN + Para.Hdr.cbJunk,
  558. pbSignedData, cbSignedData);
  559. Para.Hdr.cbSig = (USHORT)cbSignedData;
  560. ChecksumHeader();
  561. return(this->WriteHeader());
  562. }
  563. BOOL SIPObjectCAB_::ReadHeader(void)
  564. {
  565. DWORD cbOffset;
  566. BOOL fRet;
  567. this->FreeHeader();
  568. if (this->cbFileMap < sizeof(Para.Hdr.cfheader))
  569. {
  570. goto BadCABFormat;
  571. }
  572. __try {
  573. memcpy(&Para.Hdr.cfheader, &this->pbFileMap[0], sizeof(Para.Hdr.cfheader));
  574. cbOffset = sizeof(Para.Hdr.cfheader);
  575. if (Para.Hdr.cfheader.sig != sigCFHEADER)
  576. {
  577. goto BadCABFormat;
  578. }
  579. if (Para.Hdr.cfheader.flags & cfhdrRESERVE_PRESENT)
  580. {
  581. if (this->cbFileMap < (cbOffset + sizeof(Para.Hdr.cfres)))
  582. {
  583. goto BadCABFormat;
  584. }
  585. memcpy(&Para.Hdr.cfres, &this->pbFileMap[cbOffset], sizeof(Para.Hdr.cfres));
  586. cbOffset += sizeof(Para.Hdr.cfres);
  587. Para.Hdr.cbcfres = sizeof(Para.Hdr.cfres);
  588. if (Para.Hdr.cfres.cbCFHeader > 0)
  589. {
  590. if (Para.Hdr.pbReserve = (BYTE *)this->SIPNew(Para.Hdr.cfres.cbCFHeader))
  591. {
  592. if (this->cbFileMap < (cbOffset + Para.Hdr.cfres.cbCFHeader))
  593. {
  594. goto BadCABFormat;
  595. }
  596. memcpy(Para.Hdr.pbReserve, &this->pbFileMap[cbOffset], Para.Hdr.cfres.cbCFHeader);
  597. cbOffset += Para.Hdr.cfres.cbCFHeader;
  598. if (Para.Hdr.cfres.cbCFHeader >= RESERVE_CNT_HDR_LEN)
  599. {
  600. Para.Hdr.cbJunk = *((USHORT *)Para.Hdr.pbReserve);
  601. Para.Hdr.cbSig = *((USHORT *)(Para.Hdr.pbReserve + sizeof(USHORT)));
  602. if (RESERVE_CNT_HDR_LEN + Para.Hdr.cbJunk + Para.Hdr.cbSig > Para.Hdr.cfres.cbCFHeader)
  603. {
  604. goto BadCABFormat;
  605. }
  606. if (Para.Hdr.cbSig == sizeof(CABSignatureStruct_))
  607. {
  608. fUseV1Sig = FALSE;
  609. Para.Hdr.pCabSigStruct = (CABSignatureStruct_ *)(Para.Hdr.pbReserve +
  610. RESERVE_CNT_HDR_LEN +
  611. Para.Hdr.cbJunk);
  612. }
  613. else
  614. {
  615. fUseV1Sig = TRUE;
  616. }
  617. }
  618. }
  619. }
  620. }
  621. DWORD cStrings;
  622. DWORD cb;
  623. cStrings = 0;
  624. if (Para.Hdr.cfheader.flags & cfhdrPREV_CABINET)
  625. {
  626. cStrings += 2;
  627. }
  628. if (Para.Hdr.cfheader.flags & cfhdrNEXT_CABINET)
  629. {
  630. cStrings += 2;
  631. }
  632. if (cStrings > 0)
  633. {
  634. // First read to get total length of all the strings
  635. cb = 0;
  636. for (; cStrings > 0; cStrings--)
  637. {
  638. while (this->pbFileMap[cbOffset + cb])
  639. {
  640. cb++;
  641. if (this->cbFileMap < (cbOffset + cb))
  642. {
  643. goto BadCABFormat;
  644. }
  645. }
  646. //Increment the counter for the NULL terminator
  647. cb++;
  648. }
  649. if (!(Para.Hdr.pbStrings = new BYTE[cb]))
  650. {
  651. goto MemoryError;
  652. }
  653. Para.Hdr.cbStrings = cb;
  654. memcpy(Para.Hdr.pbStrings, &this->pbFileMap[cbOffset], cb);
  655. cbOffset += cb;
  656. }
  657. Para.Hdr.cbTotalHdr = sizeof(Para.Hdr.cfheader) + Para.Hdr.cbcfres +
  658. Para.Hdr.cfres.cbCFHeader + Para.Hdr.cbStrings;
  659. if ((long)Para.Hdr.cbTotalHdr > Para.Hdr.cfheader.cbCabinet)
  660. {
  661. goto BadCABFormat;
  662. }
  663. fRet = TRUE;
  664. }
  665. __except(EXCEPTION_EXECUTE_HANDLER) {
  666. SetLastError(GetExceptionCode());
  667. goto ErrorReturn;
  668. }
  669. CommonReturn:
  670. return(fRet);
  671. ErrorReturn:
  672. fRet = FALSE;
  673. goto CommonReturn;
  674. SET_ERROR_VAR_EX(DBG_SS, BadCABFormat, ERROR_BAD_FORMAT);
  675. SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY);
  676. }
  677. void SIPObjectCAB_::FreeHeader(void)
  678. {
  679. DELETE_OBJECT(Para.Hdr.pbReserve);
  680. DELETE_OBJECT(Para.Hdr.pbStrings);
  681. memset(&Para, 0x00, sizeof(CAB_PARA));
  682. }
  683. BOOL SIPObjectCAB_::WriteHeader(void)
  684. {
  685. DWORD cbWritten;
  686. // Position at beginning of file
  687. if (SetFilePointer(this->hFile, 0, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  688. {
  689. return(FALSE);
  690. }
  691. if (!(WriteFile(this->hFile, &Para.Hdr.cfheader, sizeof(Para.Hdr.cfheader),
  692. &cbWritten, NULL)) ||
  693. (cbWritten != sizeof(Para.Hdr.cfheader)))
  694. {
  695. return(FALSE);
  696. }
  697. if (Para.Hdr.cbcfres)
  698. {
  699. if (!(WriteFile(this->hFile, &Para.Hdr.cfres, sizeof(Para.Hdr.cfres),
  700. &cbWritten, NULL)) ||
  701. (cbWritten != sizeof(Para.Hdr.cfres)))
  702. {
  703. return(FALSE);
  704. }
  705. if (Para.Hdr.pbReserve)
  706. {
  707. *((USHORT *)(Para.Hdr.pbReserve + sizeof(USHORT))) = Para.Hdr.cbSig;
  708. if (!(WriteFile(this->hFile, Para.Hdr.pbReserve, Para.Hdr.cfres.cbCFHeader,
  709. &cbWritten, NULL)) ||
  710. (cbWritten != Para.Hdr.cfres.cbCFHeader))
  711. {
  712. return(FALSE);
  713. }
  714. }
  715. }
  716. if (Para.Hdr.pbStrings)
  717. {
  718. if (!(WriteFile(this->hFile, Para.Hdr.pbStrings, Para.Hdr.cbStrings,
  719. &cbWritten, NULL)) ||
  720. (cbWritten != Para.Hdr.cbStrings))
  721. {
  722. return(FALSE);
  723. }
  724. }
  725. return(TRUE);
  726. }
  727. BOOL SIPObjectCAB_::ShiftFileBytes(LONG lbShift)
  728. {
  729. LONG lStartOffset;
  730. LONG lEndOffset;
  731. LONG lNewEndOffset;
  732. LONG cbTotalMove;
  733. LONG cbMove;
  734. lStartOffset = SetFilePointer(this->hFile, 0, NULL, FILE_CURRENT);
  735. lEndOffset = (LONG)this->cbFileMap;
  736. lNewEndOffset = lEndOffset + lbShift;
  737. cbTotalMove = lEndOffset - lStartOffset;
  738. BYTE szMove[512];
  739. while (cbTotalMove)
  740. {
  741. cbMove = min(cbTotalMove, sizeof(szMove));
  742. if (lbShift > 0)
  743. {
  744. if (!(SeekAndReadFile(lEndOffset - cbMove, &szMove[0], cbMove)))
  745. {
  746. return(FALSE);
  747. }
  748. if (!(SeekAndWriteFile((lEndOffset - cbMove) + lbShift, &szMove[0], cbMove)))
  749. {
  750. return(FALSE);
  751. }
  752. lEndOffset -= cbMove;
  753. }
  754. else if (lbShift < 0)
  755. {
  756. if (!(SeekAndReadFile(lStartOffset, &szMove[0], cbMove)))
  757. {
  758. return(FALSE);
  759. }
  760. if (!(SeekAndWriteFile(lStartOffset + lbShift, &szMove[0], cbMove)))
  761. {
  762. return(FALSE);
  763. }
  764. lStartOffset += cbMove;
  765. }
  766. cbTotalMove -= cbMove;
  767. }
  768. //
  769. // Set end of file
  770. //
  771. if (SetFilePointer(this->hFile, lNewEndOffset, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  772. {
  773. return(FALSE);
  774. }
  775. this->UnmapFile();
  776. SetEndOfFile(this->hFile);
  777. return(this->MapFile());
  778. }
  779. BOOL SIPObjectCAB_::ReserveSignedData(DWORD cbSignedData)
  780. {
  781. LONG lbShift;
  782. USHORT cbReserve;
  783. if (cbSignedData != sizeof(CABSignatureStruct_))
  784. {
  785. return(FALSE);
  786. }
  787. if (SetFilePointer(this->hFile, Para.Hdr.cbTotalHdr, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  788. {
  789. return(FALSE);
  790. }
  791. fUseV1Sig = FALSE;
  792. //
  793. // Calculate length needed for CFRESERVE's abReserve[] and allocate
  794. //
  795. cbReserve = (USHORT)(RESERVE_LEN_ALIGN(RESERVE_CNT_HDR_LEN +
  796. Para.Hdr.cbJunk + cbSignedData));
  797. //
  798. // Calculate number of bytes to grow or shrink the cab file
  799. //
  800. lbShift = cbReserve - Para.Hdr.cfres.cbCFHeader;
  801. //
  802. // we're alread a v1 cab!
  803. //
  804. if (lbShift == 0)
  805. {
  806. return(TRUE);
  807. }
  808. BYTE *pbReserve;
  809. BYTE *pbFolders;
  810. DWORD cbFolders;
  811. pbFolders = NULL;
  812. cbFolders = 0;
  813. if (!(pbReserve = (BYTE *)this->SIPNew(cbReserve)))
  814. {
  815. return(FALSE);
  816. }
  817. memset(pbReserve, 0x00, cbReserve);
  818. //
  819. // Update allocated abReserve[] with counts and old junk
  820. //
  821. if (Para.Hdr.cbJunk)
  822. {
  823. *((USHORT *)pbReserve) = Para.Hdr.cbJunk;
  824. memcpy(pbReserve + RESERVE_CNT_HDR_LEN,
  825. Para.Hdr.pbReserve + RESERVE_CNT_HDR_LEN, Para.Hdr.cbJunk);
  826. }
  827. *((USHORT *)(pbReserve + sizeof(USHORT))) = (USHORT)cbSignedData;
  828. //
  829. // Update Hdr's CFRESERVE abReserve[] to reflect above changes
  830. //
  831. if (Para.Hdr.pbReserve)
  832. {
  833. delete Para.Hdr.pbReserve;
  834. Para.Hdr.pbReserve = NULL;
  835. }
  836. Para.Hdr.pbReserve = pbReserve;
  837. Para.Hdr.cfres.cbCFHeader = cbReserve;
  838. Para.Hdr.cbSig = (USHORT)cbSignedData;
  839. if (Para.Hdr.cbcfres == 0)
  840. {
  841. // Need to add CFRESERVE record
  842. Para.Hdr.cfheader.flags |= cfhdrRESERVE_PRESENT;
  843. Para.Hdr.cbcfres = sizeof(CFRESERVE);
  844. lbShift += sizeof(CFRESERVE);
  845. }
  846. //
  847. // We need to read in the folders to adjust their CFDATA file offset
  848. //
  849. if (Para.Hdr.cfheader.cFolders)
  850. {
  851. USHORT cFolders;
  852. LONG cbFolder;
  853. BYTE *pb;
  854. DWORD cbRead;
  855. cFolders = Para.Hdr.cfheader.cFolders;
  856. cbFolder = sizeof(CFFOLDER) + Para.Hdr.cfres.cbCFFolder;
  857. cbFolders = cbFolder * cFolders;
  858. if (!(pbFolders = (BYTE *)this->SIPNew(cbFolders)))
  859. {
  860. return(FALSE);
  861. }
  862. if (!(ReadFile(this->hFile, pbFolders, cbFolders, &cbRead, NULL)) ||
  863. (cbRead != cbFolders))
  864. {
  865. delete pbFolders;
  866. SetLastError(ERROR_BAD_FORMAT);
  867. return(FALSE);
  868. }
  869. pb = pbFolders;
  870. for (; cFolders > 0; cFolders--, pb += cbFolder)
  871. {
  872. ((CFFOLDER *) pb)->coffCabStart += lbShift;
  873. }
  874. }
  875. //
  876. // We need to shift the remaining contents of the cab file (CFFILE (s)
  877. // and CFDATA (s)) by lbShift
  878. //
  879. if (!(ShiftFileBytes(lbShift)))
  880. {
  881. if (pbFolders)
  882. {
  883. delete pbFolders;
  884. }
  885. return(FALSE);
  886. }
  887. //
  888. // Update lengths and offsets in the header by the delta shift needed
  889. // to store the signed data.
  890. //
  891. Para.Hdr.cbTotalHdr += lbShift;
  892. Para.Hdr.cfheader.cbCabinet += lbShift;
  893. Para.Hdr.cfheader.coffFiles += lbShift;
  894. //
  895. // pberkman - if someone starts using these, we don't want to mess them up!!!
  896. //
  897. // Para.Hdr.cfheader.csumHeader = 0;
  898. // Para.Hdr.cfheader.csumFolders = 0;
  899. // Para.Hdr.cfheader.csumFiles = 0;
  900. //
  901. // Write the header and folders back to the cab file
  902. //
  903. if (!(this->WriteHeader()))
  904. {
  905. if (pbFolders)
  906. {
  907. delete pbFolders;
  908. }
  909. return(FALSE);
  910. }
  911. if (pbFolders)
  912. {
  913. DWORD cbWritten;
  914. cbWritten = 0;
  915. if (!(WriteFile(this->hFile, pbFolders, cbFolders, &cbWritten, NULL)) ||
  916. (cbWritten != cbFolders))
  917. {
  918. delete pbFolders;
  919. return(FALSE);
  920. }
  921. delete pbFolders;
  922. }
  923. return(TRUE);
  924. }
  925. BOOL SIPObjectCAB_::DigestHeader(DIGEST_FUNCTION pfnDigestData, DIGEST_HANDLE hDigestData)
  926. {
  927. //
  928. // Digest CFHEADER, skipping the csumHeader field
  929. //
  930. if (!(pfnDigestData(hDigestData, (BYTE *)&Para.Hdr.cfheader.sig,
  931. sizeof(Para.Hdr.cfheader.sig))))
  932. {
  933. return(FALSE);
  934. }
  935. if (!(pfnDigestData(hDigestData, (BYTE *)&Para.Hdr.cfheader.cbCabinet,
  936. sizeof(CFHEADER) - sizeof(Para.Hdr.cfheader.sig) - sizeof(CHECKSUM))))
  937. {
  938. return(FALSE);
  939. }
  940. if (Para.Hdr.cbcfres)
  941. {
  942. // skip the cfres itself!
  943. if (Para.Hdr.cfres.cbCFHeader >= RESERVE_CNT_HDR_LEN)
  944. {
  945. // Digest any "junk" in abReserve[] before the signature
  946. if (!(pfnDigestData(hDigestData, (BYTE *)&Para.Hdr.cbJunk,
  947. sizeof(Para.Hdr.cbJunk))))
  948. {
  949. return(FALSE);
  950. }
  951. if (Para.Hdr.cbJunk)
  952. {
  953. if (!(pfnDigestData(hDigestData,
  954. Para.Hdr.pbReserve + RESERVE_CNT_HDR_LEN,
  955. Para.Hdr.cbJunk)))
  956. {
  957. return(FALSE);
  958. }
  959. }
  960. }
  961. }
  962. if (Para.Hdr.pbStrings)
  963. {
  964. // Digest the strings
  965. if (!(pfnDigestData(hDigestData, Para.Hdr.pbStrings, Para.Hdr.cbStrings)))
  966. {
  967. return(FALSE);
  968. }
  969. }
  970. return(TRUE);
  971. }
  972. void SIPObjectCAB_::ChecksumHeader(void)
  973. {
  974. return;
  975. // version 1 set checksum to zero. this seems to be the correct thing to do????
  976. # ifdef _DONT_USE_YET
  977. CHECKSUM csum = 0;
  978. if (Para.Hdr.cfheader.csumHeader == 0)
  979. {
  980. return;
  981. }
  982. // Checksum CFHEADER, skipping the csumHeader field
  983. csum = CSUMCompute(&Para.Hdr.cfheader.sig, sizeof(Para.Hdr.cfheader.sig), csum);
  984. csum = CSUMCompute(&Para.Hdr.cfheader.cbCabinet,
  985. sizeof(CFHEADER) -
  986. sizeof(Para.Hdr.cfheader.sig) -
  987. sizeof(CHECKSUM),
  988. csum);
  989. if (Para.Hdr.cbcfres)
  990. {
  991. csum = CSUMCompute(&Para.Hdr.cfres, sizeof(Para.Hdr.cfres), csum);
  992. if (Para.Hdr.pbReserve)
  993. {
  994. csum = CSUMCompute(Para.Hdr.pbReserve, Para.Hdr.cfres.cbCFHeader, csum);
  995. }
  996. }
  997. if (Para.Hdr.pbStrings)
  998. {
  999. csum = CSUMCompute(Para.Hdr.pbStrings, Para.Hdr.cbStrings, csum);
  1000. }
  1001. Para.Hdr.cfheader.csumHeader = csum;
  1002. # endif
  1003. }
  1004. #ifdef _DONT_USE_YET
  1005. CHECKSUM SIPObjectCAB_::CSUMCompute(void *pv, UINT cb, CHECKSUM seed)
  1006. {
  1007. int cUlong; // Number of ULONGs in block
  1008. CHECKSUM csum; // Checksum accumulator
  1009. BYTE *pb;
  1010. ULONG ul;
  1011. cUlong = cb / 4; // Number of ULONGs
  1012. csum = seed; // Init checksum
  1013. pb = (BYTE*)pv; // Start at front of data block
  1014. //** Checksum integral multiple of ULONGs
  1015. while (cUlong-- > 0) {
  1016. //** NOTE: Build ULONG in big/little-endian independent manner
  1017. ul = *pb++; // Get low-order byte
  1018. ul |= (((ULONG)(*pb++)) << 8); // Add 2nd byte
  1019. ul |= (((ULONG)(*pb++)) << 16); // Add 3nd byte
  1020. ul |= (((ULONG)(*pb++)) << 24); // Add 4th byte
  1021. csum ^= ul; // Update checksum
  1022. }
  1023. //** Checksum remainder bytes
  1024. ul = 0;
  1025. switch (cb % 4) {
  1026. case 3:
  1027. ul |= (((ULONG)(*pb++)) << 16); // Add 3nd byte
  1028. case 2:
  1029. ul |= (((ULONG)(*pb++)) << 8); // Add 2nd byte
  1030. case 1:
  1031. ul |= *pb++; // Get low-order byte
  1032. default:
  1033. break;
  1034. }
  1035. csum ^= ul; // Update checksum
  1036. //** Return computed checksum
  1037. return csum;
  1038. }
  1039. #endif // _DONT_USE_YET