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.

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