arcread.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497
  1. #include "rar.hpp"
  2. size_t Archive::ReadHeader()
  3. {
  4. // Once we failed to decrypt an encrypted block, there is no reason to
  5. // attempt to do it further. We'll never be successful and only generate
  6. // endless errors.
  7. if (FailedHeaderDecryption)
  8. return 0;
  9. CurBlockPos=Tell();
  10. // Other developers asked us to initialize it to suppress "may be used
  11. // uninitialized" warning in code below in some compilers.
  12. size_t ReadSize=0;
  13. switch(Format)
  14. {
  15. #ifndef SFX_MODULE
  16. case RARFMT14:
  17. ReadSize=ReadHeader14();
  18. break;
  19. #endif
  20. case RARFMT15:
  21. ReadSize=ReadHeader15();
  22. break;
  23. case RARFMT50:
  24. ReadSize=ReadHeader50();
  25. break;
  26. }
  27. // It is important to check ReadSize>0 here, because it is normal
  28. // for RAR2 and RAR3 archives without end of archive block to have
  29. // NextBlockPos==CurBlockPos after the end of archive has reached.
  30. if (ReadSize>0 && NextBlockPos<=CurBlockPos)
  31. {
  32. BrokenHeaderMsg();
  33. ReadSize=0;
  34. }
  35. if (ReadSize==0)
  36. CurHeaderType=HEAD_UNKNOWN;
  37. return ReadSize;
  38. }
  39. size_t Archive::SearchBlock(HEADER_TYPE HeaderType)
  40. {
  41. size_t Size,Count=0;
  42. while ((Size=ReadHeader())!=0 &&
  43. (HeaderType==HEAD_ENDARC || GetHeaderType()!=HEAD_ENDARC))
  44. {
  45. if ((++Count & 127)==0)
  46. Wait();
  47. if (GetHeaderType()==HeaderType)
  48. return Size;
  49. SeekToNext();
  50. }
  51. return 0;
  52. }
  53. size_t Archive::SearchSubBlock(const wchar *Type)
  54. {
  55. size_t Size,Count=0;
  56. while ((Size=ReadHeader())!=0 && GetHeaderType()!=HEAD_ENDARC)
  57. {
  58. if ((++Count & 127)==0)
  59. Wait();
  60. if (GetHeaderType()==HEAD_SERVICE && SubHead.CmpName(Type))
  61. return Size;
  62. SeekToNext();
  63. }
  64. return 0;
  65. }
  66. size_t Archive::SearchRR()
  67. {
  68. // If locator extra field is available for recovery record, let's utilize it.
  69. if (MainHead.Locator && MainHead.RROffset!=0)
  70. {
  71. uint64 CurPos=Tell();
  72. Seek(MainHead.RROffset,SEEK_SET);
  73. size_t Size=ReadHeader();
  74. if (Size!=0 && !BrokenHeader && GetHeaderType()==HEAD_SERVICE && SubHead.CmpName(SUBHEAD_TYPE_RR))
  75. return Size;
  76. Seek(CurPos,SEEK_SET);
  77. }
  78. // Otherwise scan the entire archive to find the recovery record.
  79. return SearchSubBlock(SUBHEAD_TYPE_RR);
  80. }
  81. void Archive::UnexpEndArcMsg()
  82. {
  83. int64 ArcSize=FileLength();
  84. // If block positions are equal to file size, this is not an error.
  85. // It can happen when we reached the end of older RAR 1.5 archive,
  86. // which did not have the end of archive block.
  87. if (CurBlockPos!=ArcSize || NextBlockPos!=ArcSize)
  88. {
  89. uiMsg(UIERROR_UNEXPEOF,FileName);
  90. ErrHandler.SetErrorCode(RARX_WARNING);
  91. }
  92. }
  93. void Archive::BrokenHeaderMsg()
  94. {
  95. uiMsg(UIERROR_HEADERBROKEN,FileName);
  96. BrokenHeader=true;
  97. ErrHandler.SetErrorCode(RARX_CRC);
  98. }
  99. void Archive::UnkEncVerMsg(const wchar *Name,const wchar *Info)
  100. {
  101. uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name,Info);
  102. ErrHandler.SetErrorCode(RARX_WARNING);
  103. }
  104. // Return f in case of signed integer overflow or negative parameters
  105. // or v1+v2 otherwise. We use it for file offsets, which are signed
  106. // for compatibility with off_t in POSIX file functions and third party code.
  107. // Signed integer overflow is the undefined behavior according to
  108. // C++ standard and it causes fuzzers to complain.
  109. inline int64 SafeAdd(int64 v1,int64 v2,int64 f)
  110. {
  111. return v1>=0 && v2>=0 && v1<=MAX_INT64-v2 ? v1+v2 : f;
  112. }
  113. size_t Archive::ReadHeader15()
  114. {
  115. RawRead Raw(this);
  116. bool Decrypt=Encrypted && CurBlockPos>(int64)SFXSize+SIZEOF_MARKHEAD3;
  117. if (Decrypt)
  118. {
  119. #ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll.
  120. return 0;
  121. #else
  122. RequestArcPassword();
  123. byte Salt[SIZE_SALT30];
  124. if (Read(Salt,SIZE_SALT30)!=SIZE_SALT30)
  125. {
  126. UnexpEndArcMsg();
  127. return 0;
  128. }
  129. HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL);
  130. Raw.SetCrypt(&HeadersCrypt);
  131. #endif
  132. }
  133. Raw.Read(SIZEOF_SHORTBLOCKHEAD);
  134. if (Raw.Size()==0)
  135. {
  136. UnexpEndArcMsg();
  137. return 0;
  138. }
  139. ShortBlock.HeadCRC=Raw.Get2();
  140. ShortBlock.Reset();
  141. uint HeaderType=Raw.Get1();
  142. ShortBlock.Flags=Raw.Get2();
  143. ShortBlock.SkipIfUnknown=(ShortBlock.Flags & SKIP_IF_UNKNOWN)!=0;
  144. ShortBlock.HeadSize=Raw.Get2();
  145. ShortBlock.HeaderType=(HEADER_TYPE)HeaderType;
  146. if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
  147. {
  148. BrokenHeaderMsg();
  149. return 0;
  150. }
  151. // For simpler further processing we map header types common
  152. // for RAR 1.5 and 5.0 formats to RAR 5.0 values. It does not include
  153. // header types specific for RAR 1.5 - 4.x only.
  154. switch(ShortBlock.HeaderType)
  155. {
  156. case HEAD3_MAIN: ShortBlock.HeaderType=HEAD_MAIN; break;
  157. case HEAD3_FILE: ShortBlock.HeaderType=HEAD_FILE; break;
  158. case HEAD3_SERVICE: ShortBlock.HeaderType=HEAD_SERVICE; break;
  159. case HEAD3_ENDARC: ShortBlock.HeaderType=HEAD_ENDARC; break;
  160. }
  161. CurHeaderType=ShortBlock.HeaderType;
  162. if (ShortBlock.HeaderType==HEAD3_CMT)
  163. {
  164. // Old style (up to RAR 2.9) comment header embedded into main
  165. // or file header. We must not read the entire ShortBlock.HeadSize here
  166. // to not break the comment processing logic later.
  167. Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
  168. }
  169. else
  170. if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0)
  171. {
  172. // Old style (up to RAR 2.9) main archive comment embedded into
  173. // the main archive header found. While we can read the entire
  174. // ShortBlock.HeadSize here and remove this part of "if", it would be
  175. // waste of memory, because we'll read and process this comment data
  176. // in other function anyway and we do not need them here now.
  177. Raw.Read(SIZEOF_MAINHEAD3-SIZEOF_SHORTBLOCKHEAD);
  178. }
  179. else
  180. Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);
  181. NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize);
  182. switch(ShortBlock.HeaderType)
  183. {
  184. case HEAD_MAIN:
  185. MainHead.Reset();
  186. *(BaseBlock *)&MainHead=ShortBlock;
  187. MainHead.HighPosAV=Raw.Get2();
  188. MainHead.PosAV=Raw.Get4();
  189. Volume=(MainHead.Flags & MHD_VOLUME)!=0;
  190. Solid=(MainHead.Flags & MHD_SOLID)!=0;
  191. Locked=(MainHead.Flags & MHD_LOCK)!=0;
  192. Protected=(MainHead.Flags & MHD_PROTECT)!=0;
  193. Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0;
  194. Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0;
  195. MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
  196. // Only for encrypted 3.0+ archives. 2.x archives did not have this
  197. // flag, so for non-encrypted archives, we'll set it later based on
  198. // file attributes.
  199. FirstVolume=(MainHead.Flags & MHD_FIRSTVOLUME)!=0;
  200. NewNumbering=(MainHead.Flags & MHD_NEWNUMBERING)!=0;
  201. break;
  202. case HEAD_FILE:
  203. case HEAD_SERVICE:
  204. {
  205. bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
  206. FileHeader *hd=FileBlock ? &FileHead:&SubHead;
  207. hd->Reset();
  208. *(BaseBlock *)hd=ShortBlock;
  209. hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0;
  210. hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0;
  211. hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0;
  212. hd->SaltSet=(hd->Flags & LHD_SALT)!=0;
  213. hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0;
  214. hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0;
  215. hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
  216. hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
  217. hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
  218. hd->Version=(hd->Flags & LHD_VERSION)!=0;
  219. hd->DataSize=Raw.Get4();
  220. uint LowUnpSize=Raw.Get4();
  221. hd->HostOS=Raw.Get1();
  222. hd->FileHash.Type=HASH_CRC32;
  223. hd->FileHash.CRC32=Raw.Get4();
  224. uint FileTime=Raw.Get4();
  225. hd->UnpVer=Raw.Get1();
  226. hd->Method=Raw.Get1()-0x30;
  227. size_t NameSize=Raw.Get2();
  228. hd->FileAttr=Raw.Get4();
  229. // RAR15 did not use the special dictionary size to mark dirs.
  230. if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0)
  231. hd->Dir=true;
  232. hd->CryptMethod=CRYPT_NONE;
  233. if (hd->Encrypted)
  234. switch(hd->UnpVer)
  235. {
  236. case 13: hd->CryptMethod=CRYPT_RAR13; break;
  237. case 15: hd->CryptMethod=CRYPT_RAR15; break;
  238. case 20:
  239. case 26: hd->CryptMethod=CRYPT_RAR20; break;
  240. default: hd->CryptMethod=CRYPT_RAR30; break;
  241. }
  242. hd->HSType=HSYS_UNKNOWN;
  243. if (hd->HostOS==HOST_UNIX || hd->HostOS==HOST_BEOS)
  244. hd->HSType=HSYS_UNIX;
  245. else
  246. if (hd->HostOS<HOST_MAX)
  247. hd->HSType=HSYS_WINDOWS;
  248. hd->RedirType=FSREDIR_NONE;
  249. // RAR 4.x Unix symlink.
  250. if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000)
  251. {
  252. hd->RedirType=FSREDIR_UNIXSYMLINK;
  253. *hd->RedirName=0;
  254. }
  255. hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
  256. hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;
  257. uint HighPackSize,HighUnpSize;
  258. if (hd->LargeFile)
  259. {
  260. HighPackSize=Raw.Get4();
  261. HighUnpSize=Raw.Get4();
  262. hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
  263. }
  264. else
  265. {
  266. HighPackSize=HighUnpSize=0;
  267. // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
  268. // that we do not know the unpacked file size and must unpack it
  269. // until we find the end of file marker in compressed data.
  270. hd->UnknownUnpSize=(LowUnpSize==0xffffffff);
  271. }
  272. hd->PackSize=INT32TO64(HighPackSize,hd->DataSize);
  273. hd->UnpSize=INT32TO64(HighUnpSize,LowUnpSize);
  274. if (hd->UnknownUnpSize)
  275. hd->UnpSize=INT64NDF;
  276. char FileName[NM*4];
  277. size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
  278. Raw.GetB((byte *)FileName,ReadNameSize);
  279. FileName[ReadNameSize]=0;
  280. if (FileBlock)
  281. {
  282. *hd->FileName=0;
  283. if ((hd->Flags & LHD_UNICODE)!=0)
  284. {
  285. EncodeFileName NameCoder;
  286. size_t Length=strlen(FileName);
  287. Length++;
  288. if (ReadNameSize>Length)
  289. NameCoder.Decode(FileName,ReadNameSize,(byte *)FileName+Length,
  290. ReadNameSize-Length,hd->FileName,
  291. ASIZE(hd->FileName));
  292. }
  293. if (*hd->FileName==0)
  294. ArcCharToWide(FileName,hd->FileName,ASIZE(hd->FileName),ACTW_OEM);
  295. #ifndef SFX_MODULE
  296. ConvertNameCase(hd->FileName);
  297. #endif
  298. ConvertFileHeader(hd);
  299. }
  300. else
  301. {
  302. CharToWide(FileName,hd->FileName,ASIZE(hd->FileName));
  303. // Calculate the size of optional data.
  304. int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3);
  305. if ((hd->Flags & LHD_SALT)!=0)
  306. DataSize-=SIZE_SALT30;
  307. if (DataSize>0)
  308. {
  309. // Here we read optional additional fields for subheaders.
  310. // They are stored after the file name and before salt.
  311. hd->SubData.Alloc(DataSize);
  312. Raw.GetB(&hd->SubData[0],DataSize);
  313. }
  314. if (hd->CmpName(SUBHEAD_TYPE_CMT))
  315. MainComment=true;
  316. }
  317. if ((hd->Flags & LHD_SALT)!=0)
  318. Raw.GetB(hd->Salt,SIZE_SALT30);
  319. hd->mtime.SetDos(FileTime);
  320. if ((hd->Flags & LHD_EXTTIME)!=0)
  321. {
  322. ushort Flags=Raw.Get2();
  323. RarTime *tbl[4];
  324. tbl[0]=&FileHead.mtime;
  325. tbl[1]=&FileHead.ctime;
  326. tbl[2]=&FileHead.atime;
  327. tbl[3]=NULL; // Archive time is not used now.
  328. for (int I=0;I<4;I++)
  329. {
  330. RarTime *CurTime=tbl[I];
  331. uint rmode=Flags>>(3-I)*4;
  332. if ((rmode & 8)==0 || CurTime==NULL)
  333. continue;
  334. if (I!=0)
  335. {
  336. uint DosTime=Raw.Get4();
  337. CurTime->SetDos(DosTime);
  338. }
  339. RarLocalTime rlt;
  340. CurTime->GetLocal(&rlt);
  341. if (rmode & 4)
  342. rlt.Second++;
  343. rlt.Reminder=0;
  344. uint count=rmode&3;
  345. for (uint J=0;J<count;J++)
  346. {
  347. byte CurByte=Raw.Get1();
  348. rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
  349. }
  350. // Convert from 100ns RAR precision to REMINDER_PRECISION.
  351. rlt.Reminder*=RarTime::REMINDER_PRECISION/10000000;
  352. CurTime->SetLocal(&rlt);
  353. }
  354. }
  355. // Set to 0 in case of overflow, so end of ReadHeader cares about it.
  356. NextBlockPos=SafeAdd(NextBlockPos,hd->PackSize,0);
  357. bool CRCProcessedOnly=hd->CommentInHeader;
  358. ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly);
  359. if (hd->HeadCRC!=HeaderCRC)
  360. {
  361. BrokenHeader=true;
  362. ErrHandler.SetErrorCode(RARX_WARNING);
  363. // If we have a broken encrypted header, we do not need to display
  364. // the error message here, because it will be displayed for such
  365. // headers later in this function. Also such headers are unlikely
  366. // to have anything sensible in file name field, so it is useless
  367. // to display the file name.
  368. if (!Decrypt)
  369. uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
  370. }
  371. }
  372. break;
  373. case HEAD_ENDARC:
  374. *(BaseBlock *)&EndArcHead=ShortBlock;
  375. EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0;
  376. EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0;
  377. EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0;
  378. EndArcHead.StoreVolNumber=(EndArcHead.Flags & EARC_VOLNUMBER)!=0;
  379. if (EndArcHead.DataCRC)
  380. EndArcHead.ArcDataCRC=Raw.Get4();
  381. if (EndArcHead.StoreVolNumber)
  382. VolNumber=EndArcHead.VolNumber=Raw.Get2();
  383. break;
  384. #ifndef SFX_MODULE
  385. case HEAD3_CMT:
  386. *(BaseBlock *)&CommHead=ShortBlock;
  387. CommHead.UnpSize=Raw.Get2();
  388. CommHead.UnpVer=Raw.Get1();
  389. CommHead.Method=Raw.Get1();
  390. CommHead.CommCRC=Raw.Get2();
  391. break;
  392. case HEAD3_PROTECT:
  393. *(BaseBlock *)&ProtectHead=ShortBlock;
  394. ProtectHead.DataSize=Raw.Get4();
  395. ProtectHead.Version=Raw.Get1();
  396. ProtectHead.RecSectors=Raw.Get2();
  397. ProtectHead.TotalBlocks=Raw.Get4();
  398. Raw.GetB(ProtectHead.Mark,8);
  399. NextBlockPos+=ProtectHead.DataSize;
  400. break;
  401. case HEAD3_OLDSERVICE: // RAR 2.9 and earlier.
  402. *(BaseBlock *)&SubBlockHead=ShortBlock;
  403. SubBlockHead.DataSize=Raw.Get4();
  404. NextBlockPos+=SubBlockHead.DataSize;
  405. SubBlockHead.SubType=Raw.Get2();
  406. SubBlockHead.Level=Raw.Get1();
  407. switch(SubBlockHead.SubType)
  408. {
  409. case UO_HEAD:
  410. *(SubBlockHeader *)&UOHead=SubBlockHead;
  411. UOHead.OwnerNameSize=Raw.Get2();
  412. UOHead.GroupNameSize=Raw.Get2();
  413. if (UOHead.OwnerNameSize>=ASIZE(UOHead.OwnerName))
  414. UOHead.OwnerNameSize=ASIZE(UOHead.OwnerName)-1;
  415. if (UOHead.GroupNameSize>=ASIZE(UOHead.GroupName))
  416. UOHead.GroupNameSize=ASIZE(UOHead.GroupName)-1;
  417. Raw.GetB(UOHead.OwnerName,UOHead.OwnerNameSize);
  418. Raw.GetB(UOHead.GroupName,UOHead.GroupNameSize);
  419. UOHead.OwnerName[UOHead.OwnerNameSize]=0;
  420. UOHead.GroupName[UOHead.GroupNameSize]=0;
  421. break;
  422. case NTACL_HEAD:
  423. *(SubBlockHeader *)&EAHead=SubBlockHead;
  424. EAHead.UnpSize=Raw.Get4();
  425. EAHead.UnpVer=Raw.Get1();
  426. EAHead.Method=Raw.Get1();
  427. EAHead.EACRC=Raw.Get4();
  428. break;
  429. case STREAM_HEAD:
  430. *(SubBlockHeader *)&StreamHead=SubBlockHead;
  431. StreamHead.UnpSize=Raw.Get4();
  432. StreamHead.UnpVer=Raw.Get1();
  433. StreamHead.Method=Raw.Get1();
  434. StreamHead.StreamCRC=Raw.Get4();
  435. StreamHead.StreamNameSize=Raw.Get2();
  436. if (StreamHead.StreamNameSize>=ASIZE(StreamHead.StreamName))
  437. StreamHead.StreamNameSize=ASIZE(StreamHead.StreamName)-1;
  438. Raw.GetB(StreamHead.StreamName,StreamHead.StreamNameSize);
  439. StreamHead.StreamName[StreamHead.StreamNameSize]=0;
  440. break;
  441. }
  442. break;
  443. #endif
  444. default:
  445. if (ShortBlock.Flags & LONG_BLOCK)
  446. NextBlockPos+=Raw.Get4();
  447. break;
  448. }
  449. ushort HeaderCRC=Raw.GetCRC15(false);
  450. // Old AV header does not have header CRC properly set.
  451. if (ShortBlock.HeadCRC!=HeaderCRC && ShortBlock.HeaderType!=HEAD3_SIGN &&
  452. ShortBlock.HeaderType!=HEAD3_AV)
  453. {
  454. bool Recovered=false;
  455. if (ShortBlock.HeaderType==HEAD_ENDARC && EndArcHead.RevSpace)
  456. {
  457. // Last 7 bytes of recovered volume can contain zeroes, because
  458. // REV files store its own information (volume number, etc.) here.
  459. int64 Length=Tell();
  460. Seek(Length-7,SEEK_SET);
  461. Recovered=true;
  462. for (int J=0;J<7;J++)
  463. if (GetByte()!=0)
  464. Recovered=false;
  465. }
  466. if (!Recovered)
  467. {
  468. BrokenHeader=true;
  469. ErrHandler.SetErrorCode(RARX_CRC);
  470. if (Decrypt)
  471. {
  472. uiMsg(UIERROR_CHECKSUMENC,FileName,FileName);
  473. FailedHeaderDecryption=true;
  474. return 0;
  475. }
  476. }
  477. }
  478. return Raw.Size();
  479. }
  480. size_t Archive::ReadHeader50()
  481. {
  482. RawRead Raw(this);
  483. bool Decrypt=Encrypted && CurBlockPos>(int64)SFXSize+SIZEOF_MARKHEAD5;
  484. if (Decrypt)
  485. {
  486. #if defined(RAR_NOCRYPT)
  487. return 0;
  488. #else
  489. if (Cmd->SkipEncrypted)
  490. {
  491. uiMsg(UIMSG_SKIPENCARC,FileName);
  492. FailedHeaderDecryption=true; // Suppress error messages and quit quietly.
  493. return 0;
  494. }
  495. byte HeadersInitV[SIZE_INITV];
  496. if (Read(HeadersInitV,SIZE_INITV)!=SIZE_INITV)
  497. {
  498. UnexpEndArcMsg();
  499. return 0;
  500. }
  501. // We repeat the password request only for manually entered passwords
  502. // and not for -p<pwd>. Wrong password can be intentionally provided
  503. // in -p<pwd> to not stop batch processing for encrypted archives.
  504. bool GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet();
  505. while (true) // Repeat the password prompt for wrong passwords.
  506. {
  507. RequestArcPassword();
  508. byte PswCheck[SIZE_PSWCHECK];
  509. HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck);
  510. // Verify password validity.
  511. if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
  512. {
  513. if (GlobalPassword) // For -p<pwd> or Ctrl+P.
  514. {
  515. // This message is used by Android GUI to reset cached passwords.
  516. // Update appropriate code if changed.
  517. uiMsg(UIERROR_BADPSW,FileName,FileName);
  518. FailedHeaderDecryption=true;
  519. ErrHandler.SetErrorCode(RARX_BADPWD);
  520. return 0;
  521. }
  522. else // For passwords entered manually.
  523. {
  524. // This message is used by Android GUI and Windows GUI and SFX to
  525. // reset cached passwords. Update appropriate code if changed.
  526. uiMsg(UIWAIT_BADPSW,FileName,FileName);
  527. Cmd->Password.Clean();
  528. }
  529. #ifdef RARDLL
  530. // Avoid new requests for unrar.dll to prevent the infinite loop
  531. // if app always returns the same password.
  532. ErrHandler.SetErrorCode(RARX_BADPWD);
  533. Cmd->DllError=ERAR_BAD_PASSWORD;
  534. ErrHandler.Exit(RARX_BADPWD);
  535. #else
  536. continue; // Request a password again.
  537. #endif
  538. }
  539. break;
  540. }
  541. Raw.SetCrypt(&HeadersCrypt);
  542. #endif
  543. }
  544. // Header size must not occupy more than 3 variable length integer bytes
  545. // resulting in 2 MB maximum header size (MAX_HEADER_SIZE_RAR5),
  546. // so here we read 4 byte CRC32 followed by 3 bytes or less of header size.
  547. const size_t FirstReadSize=7; // Smallest possible block size.
  548. if (Raw.Read(FirstReadSize)<FirstReadSize)
  549. {
  550. UnexpEndArcMsg();
  551. return 0;
  552. }
  553. ShortBlock.Reset();
  554. ShortBlock.HeadCRC=Raw.Get4();
  555. uint SizeBytes=Raw.GetVSize(4);
  556. uint64 BlockSize=Raw.GetV();
  557. if (BlockSize==0 || SizeBytes==0)
  558. {
  559. BrokenHeaderMsg();
  560. return 0;
  561. }
  562. int SizeToRead=int(BlockSize);
  563. SizeToRead-=FirstReadSize-SizeBytes-4; // Adjust overread size bytes if any.
  564. uint HeaderSize=4+SizeBytes+(uint)BlockSize;
  565. if (SizeToRead<0 || HeaderSize<SIZEOF_SHORTBLOCKHEAD5)
  566. {
  567. BrokenHeaderMsg();
  568. return 0;
  569. }
  570. Raw.Read(SizeToRead);
  571. if (Raw.Size()<HeaderSize)
  572. {
  573. UnexpEndArcMsg();
  574. return 0;
  575. }
  576. uint HeaderCRC=Raw.GetCRC50();
  577. ShortBlock.HeaderType=(HEADER_TYPE)Raw.GetV();
  578. ShortBlock.Flags=(uint)Raw.GetV();
  579. ShortBlock.SkipIfUnknown=(ShortBlock.Flags & HFL_SKIPIFUNKNOWN)!=0;
  580. ShortBlock.HeadSize=HeaderSize;
  581. CurHeaderType=ShortBlock.HeaderType;
  582. bool BadCRC=(ShortBlock.HeadCRC!=HeaderCRC);
  583. if (BadCRC)
  584. {
  585. BrokenHeaderMsg(); // Report, but attempt to process.
  586. BrokenHeader=true;
  587. ErrHandler.SetErrorCode(RARX_CRC);
  588. if (Decrypt)
  589. {
  590. uiMsg(UIERROR_CHECKSUMENC,FileName,FileName);
  591. FailedHeaderDecryption=true;
  592. return 0;
  593. }
  594. }
  595. uint64 ExtraSize=0;
  596. if ((ShortBlock.Flags & HFL_EXTRA)!=0)
  597. {
  598. ExtraSize=Raw.GetV();
  599. if (ExtraSize>=ShortBlock.HeadSize)
  600. {
  601. BrokenHeaderMsg();
  602. return 0;
  603. }
  604. }
  605. uint64 DataSize=0;
  606. if ((ShortBlock.Flags & HFL_DATA)!=0)
  607. DataSize=Raw.GetV();
  608. NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize);
  609. // Set to 0 in case of overflow, so end of ReadHeader cares about it.
  610. NextBlockPos=SafeAdd(NextBlockPos,DataSize,0);
  611. switch(ShortBlock.HeaderType)
  612. {
  613. case HEAD_CRYPT:
  614. {
  615. *(BaseBlock *)&CryptHead=ShortBlock;
  616. uint CryptVersion=(uint)Raw.GetV();
  617. if (CryptVersion>CRYPT_VERSION)
  618. {
  619. wchar Info[20];
  620. swprintf(Info,ASIZE(Info),L"h%u",CryptVersion);
  621. UnkEncVerMsg(FileName,Info);
  622. return 0;
  623. }
  624. uint EncFlags=(uint)Raw.GetV();
  625. CryptHead.UsePswCheck=(EncFlags & CHFL_CRYPT_PSWCHECK)!=0;
  626. CryptHead.Lg2Count=Raw.Get1();
  627. if (CryptHead.Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
  628. {
  629. wchar Info[20];
  630. swprintf(Info,ASIZE(Info),L"hc%u",CryptHead.Lg2Count);
  631. UnkEncVerMsg(FileName,Info);
  632. return 0;
  633. }
  634. Raw.GetB(CryptHead.Salt,SIZE_SALT50);
  635. if (CryptHead.UsePswCheck)
  636. {
  637. Raw.GetB(CryptHead.PswCheck,SIZE_PSWCHECK);
  638. byte csum[SIZE_PSWCHECK_CSUM];
  639. Raw.GetB(csum,SIZE_PSWCHECK_CSUM);
  640. sha256_context ctx;
  641. sha256_init(&ctx);
  642. sha256_process(&ctx, CryptHead.PswCheck, SIZE_PSWCHECK);
  643. byte Digest[SHA256_DIGEST_SIZE];
  644. sha256_done(&ctx, Digest);
  645. CryptHead.UsePswCheck=memcmp(csum,Digest,SIZE_PSWCHECK_CSUM)==0;
  646. }
  647. Encrypted=true;
  648. }
  649. break;
  650. case HEAD_MAIN:
  651. {
  652. MainHead.Reset();
  653. *(BaseBlock *)&MainHead=ShortBlock;
  654. uint ArcFlags=(uint)Raw.GetV();
  655. Volume=(ArcFlags & MHFL_VOLUME)!=0;
  656. Solid=(ArcFlags & MHFL_SOLID)!=0;
  657. Locked=(ArcFlags & MHFL_LOCK)!=0;
  658. Protected=(ArcFlags & MHFL_PROTECT)!=0;
  659. Signed=false;
  660. NewNumbering=true;
  661. if ((ArcFlags & MHFL_VOLNUMBER)!=0)
  662. VolNumber=(uint)Raw.GetV();
  663. else
  664. VolNumber=0;
  665. FirstVolume=Volume && VolNumber==0;
  666. if (ExtraSize!=0)
  667. ProcessExtra50(&Raw,(size_t)ExtraSize,&MainHead);
  668. #ifdef USE_QOPEN
  669. if (!ProhibitQOpen && MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE)
  670. {
  671. // We seek to QO block in the end of archive when processing
  672. // QOpen.Load, so we need to preserve current block positions
  673. // to not break normal archive processing by calling function.
  674. int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
  675. HEADER_TYPE SaveCurHeaderType=CurHeaderType;
  676. QOpen.Init(this,false);
  677. QOpen.Load(MainHead.QOpenOffset);
  678. CurBlockPos=SaveCurBlockPos;
  679. NextBlockPos=SaveNextBlockPos;
  680. CurHeaderType=SaveCurHeaderType;
  681. }
  682. #endif
  683. }
  684. break;
  685. case HEAD_FILE:
  686. case HEAD_SERVICE:
  687. {
  688. FileHeader *hd=ShortBlock.HeaderType==HEAD_FILE ? &FileHead:&SubHead;
  689. hd->Reset(); // Clear hash, time fields and other stuff like flags.
  690. *(BaseBlock *)hd=ShortBlock;
  691. bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
  692. hd->LargeFile=true;
  693. hd->PackSize=DataSize;
  694. hd->FileFlags=(uint)Raw.GetV();
  695. hd->UnpSize=Raw.GetV();
  696. hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0;
  697. if (hd->UnknownUnpSize)
  698. hd->UnpSize=INT64NDF;
  699. hd->MaxSize=Max(hd->PackSize,hd->UnpSize);
  700. hd->FileAttr=(uint)Raw.GetV();
  701. if ((hd->FileFlags & FHFL_UTIME)!=0)
  702. hd->mtime.SetUnix((time_t)Raw.Get4());
  703. hd->FileHash.Type=HASH_NONE;
  704. if ((hd->FileFlags & FHFL_CRC32)!=0)
  705. {
  706. hd->FileHash.Type=HASH_CRC32;
  707. hd->FileHash.CRC32=Raw.Get4();
  708. }
  709. hd->RedirType=FSREDIR_NONE;
  710. uint CompInfo=(uint)Raw.GetV();
  711. hd->Method=(CompInfo>>7) & 7;
  712. // "+ 50" to not mix with old RAR format algorithms. For example,
  713. // we may need to use the compression algorithm 15 in the future,
  714. // but it was already used in RAR 1.5 and Unpack needs to distinguish
  715. // them.
  716. hd->UnpVer=(CompInfo & 0x3f) + 50;
  717. if (hd->UnpVer!=50) // Only 5.0 compression is known now.
  718. hd->UnpVer=VER_UNKNOWN;
  719. hd->HostOS=(byte)Raw.GetV();
  720. size_t NameSize=(size_t)Raw.GetV();
  721. hd->Inherited=(ShortBlock.Flags & HFL_INHERITED)!=0;
  722. hd->HSType=HSYS_UNKNOWN;
  723. if (hd->HostOS==HOST5_UNIX)
  724. hd->HSType=HSYS_UNIX;
  725. else
  726. if (hd->HostOS==HOST5_WINDOWS)
  727. hd->HSType=HSYS_WINDOWS;
  728. hd->SplitBefore=(hd->Flags & HFL_SPLITBEFORE)!=0;
  729. hd->SplitAfter=(hd->Flags & HFL_SPLITAFTER)!=0;
  730. hd->SubBlock=(hd->Flags & HFL_CHILD)!=0;
  731. hd->Solid=FileBlock && (CompInfo & FCI_SOLID)!=0;
  732. hd->Dir=(hd->FileFlags & FHFL_DIRECTORY)!=0;
  733. hd->WinSize=hd->Dir ? 0:size_t(0x20000)<<((CompInfo>>10)&0xf);
  734. hd->CryptMethod=hd->Encrypted ? CRYPT_RAR50:CRYPT_NONE;
  735. char FileName[NM*4];
  736. size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
  737. Raw.GetB((byte *)FileName,ReadNameSize);
  738. FileName[ReadNameSize]=0;
  739. UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName));
  740. // Should do it before converting names, because extra fields can
  741. // affect name processing, like in case of NTFS streams.
  742. if (ExtraSize!=0)
  743. ProcessExtra50(&Raw,(size_t)ExtraSize,hd);
  744. if (FileBlock)
  745. {
  746. #ifndef SFX_MODULE
  747. ConvertNameCase(hd->FileName);
  748. #endif
  749. ConvertFileHeader(hd);
  750. }
  751. if (!FileBlock && hd->CmpName(SUBHEAD_TYPE_CMT))
  752. MainComment=true;
  753. #if 0
  754. // For RAR5 format we read the user specified recovery percent here.
  755. // It would be useful to do it for shell extension too, so we display
  756. // the correct recovery record size in archive properties. But then
  757. // we would need to include the entire recovery record processing
  758. // code to shell extension, which is not done now.
  759. if (!FileBlock && hd->CmpName(SUBHEAD_TYPE_RR) && hd->SubData.Size()>0)
  760. {
  761. // It is stored as a single byte up to RAR 6.02 and as vint since
  762. // 6.10, where we extended the maximum RR size from 99% to 1000%.
  763. RawRead RawPercent;
  764. RawPercent.Read(&hd->SubData[0],hd->SubData.Size());
  765. RecoveryPercent=(int)RawPercent.GetV();
  766. RSBlockHeader Header;
  767. GetRRInfo(this,&Header);
  768. RecoverySize=Header.RecSectionSize*Header.RecCount;
  769. }
  770. #endif
  771. if (BadCRC) // Add the file name to broken header message displayed above.
  772. uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
  773. }
  774. break;
  775. case HEAD_ENDARC:
  776. {
  777. *(BaseBlock *)&EndArcHead=ShortBlock;
  778. uint ArcFlags=(uint)Raw.GetV();
  779. EndArcHead.NextVolume=(ArcFlags & EHFL_NEXTVOLUME)!=0;
  780. EndArcHead.StoreVolNumber=false;
  781. EndArcHead.DataCRC=false;
  782. EndArcHead.RevSpace=false;
  783. }
  784. break;
  785. }
  786. return Raw.Size();
  787. }
  788. #if !defined(RAR_NOCRYPT)
  789. void Archive::RequestArcPassword()
  790. {
  791. if (!Cmd->Password.IsSet())
  792. {
  793. #ifdef RARDLL
  794. if (Cmd->Callback!=NULL)
  795. {
  796. wchar PasswordW[MAXPASSWORD];
  797. *PasswordW=0;
  798. if (Cmd->Callback(UCM_NEEDPASSWORDW,Cmd->UserData,(LPARAM)PasswordW,ASIZE(PasswordW))==-1)
  799. *PasswordW=0;
  800. if (*PasswordW==0)
  801. {
  802. char PasswordA[MAXPASSWORD];
  803. *PasswordA=0;
  804. if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
  805. *PasswordA=0;
  806. GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW));
  807. cleandata(PasswordA,sizeof(PasswordA));
  808. }
  809. Cmd->Password.Set(PasswordW);
  810. cleandata(PasswordW,sizeof(PasswordW));
  811. }
  812. if (!Cmd->Password.IsSet())
  813. {
  814. Close();
  815. Cmd->DllError=ERAR_MISSING_PASSWORD;
  816. ErrHandler.Exit(RARX_USERBREAK);
  817. }
  818. #else
  819. if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password))
  820. {
  821. Close();
  822. uiMsg(UIERROR_INCERRCOUNT); // Prevent archive deleting if delete after extraction is on.
  823. ErrHandler.Exit(RARX_USERBREAK);
  824. }
  825. #endif
  826. Cmd->ManualPassword=true;
  827. }
  828. }
  829. #endif
  830. void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
  831. {
  832. // Read extra data from the end of block skipping any fields before it.
  833. size_t ExtraStart=Raw->Size()-ExtraSize;
  834. if (ExtraStart<Raw->GetPos())
  835. return;
  836. Raw->SetPos(ExtraStart);
  837. while (Raw->DataLeft()>=2)
  838. {
  839. int64 FieldSize=Raw->GetV(); // Needs to be signed for check below and can be negative.
  840. if (FieldSize<=0 || Raw->DataLeft()==0 || FieldSize>(int64)Raw->DataLeft())
  841. break;
  842. size_t NextPos=size_t(Raw->GetPos()+FieldSize);
  843. uint64 FieldType=Raw->GetV();
  844. FieldSize=int64(NextPos-Raw->GetPos()); // Field size without size and type fields.
  845. if (FieldSize<0) // FieldType is longer than expected extra field size.
  846. break;
  847. if (bb->HeaderType==HEAD_MAIN)
  848. {
  849. MainHeader *hd=(MainHeader *)bb;
  850. if (FieldType==MHEXTRA_LOCATOR)
  851. {
  852. hd->Locator=true;
  853. uint Flags=(uint)Raw->GetV();
  854. if ((Flags & MHEXTRA_LOCATOR_QLIST)!=0)
  855. {
  856. uint64 Offset=Raw->GetV();
  857. if (Offset!=0) // 0 means that reserved space was not enough to write the offset.
  858. hd->QOpenOffset=Offset+CurBlockPos;
  859. }
  860. if ((Flags & MHEXTRA_LOCATOR_RR)!=0)
  861. {
  862. uint64 Offset=Raw->GetV();
  863. if (Offset!=0) // 0 means that reserved space was not enough to write the offset.
  864. hd->RROffset=Offset+CurBlockPos;
  865. }
  866. }
  867. }
  868. if (bb->HeaderType==HEAD_FILE || bb->HeaderType==HEAD_SERVICE)
  869. {
  870. FileHeader *hd=(FileHeader *)bb;
  871. switch(FieldType)
  872. {
  873. case FHEXTRA_CRYPT:
  874. {
  875. FileHeader *hd=(FileHeader *)bb;
  876. uint EncVersion=(uint)Raw->GetV();
  877. if (EncVersion>CRYPT_VERSION)
  878. {
  879. wchar Info[20];
  880. swprintf(Info,ASIZE(Info),L"x%u",EncVersion);
  881. UnkEncVerMsg(hd->FileName,Info);
  882. }
  883. else
  884. {
  885. uint Flags=(uint)Raw->GetV();
  886. hd->UsePswCheck=(Flags & FHEXTRA_CRYPT_PSWCHECK)!=0;
  887. hd->UseHashKey=(Flags & FHEXTRA_CRYPT_HASHMAC)!=0;
  888. hd->Lg2Count=Raw->Get1();
  889. if (hd->Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
  890. {
  891. wchar Info[20];
  892. swprintf(Info,ASIZE(Info),L"xc%u",hd->Lg2Count);
  893. UnkEncVerMsg(hd->FileName,Info);
  894. }
  895. Raw->GetB(hd->Salt,SIZE_SALT50);
  896. Raw->GetB(hd->InitV,SIZE_INITV);
  897. if (hd->UsePswCheck)
  898. {
  899. Raw->GetB(hd->PswCheck,SIZE_PSWCHECK);
  900. // It is important to know if password check data is valid.
  901. // If it is damaged and header CRC32 fails to detect it,
  902. // archiver would refuse to decompress a possibly valid file.
  903. // Since we want to be sure distinguishing a wrong password
  904. // or corrupt file data, we use 64-bit password check data
  905. // and to control its validity we use 32 bits of password
  906. // check data SHA-256 additionally to 32-bit header CRC32.
  907. byte csum[SIZE_PSWCHECK_CSUM];
  908. Raw->GetB(csum,SIZE_PSWCHECK_CSUM);
  909. sha256_context ctx;
  910. sha256_init(&ctx);
  911. sha256_process(&ctx, hd->PswCheck, SIZE_PSWCHECK);
  912. byte Digest[SHA256_DIGEST_SIZE];
  913. sha256_done(&ctx, Digest);
  914. hd->UsePswCheck=memcmp(csum,Digest,SIZE_PSWCHECK_CSUM)==0;
  915. // RAR 5.21 and earlier set PswCheck field in service records to 0
  916. // even if UsePswCheck was present.
  917. if (bb->HeaderType==HEAD_SERVICE && memcmp(hd->PswCheck,"\0\0\0\0\0\0\0\0",SIZE_PSWCHECK)==0)
  918. hd->UsePswCheck=0;
  919. }
  920. hd->SaltSet=true;
  921. hd->CryptMethod=CRYPT_RAR50;
  922. hd->Encrypted=true;
  923. }
  924. }
  925. break;
  926. case FHEXTRA_HASH:
  927. {
  928. FileHeader *hd=(FileHeader *)bb;
  929. uint Type=(uint)Raw->GetV();
  930. if (Type==FHEXTRA_HASH_BLAKE2)
  931. {
  932. hd->FileHash.Type=HASH_BLAKE2;
  933. Raw->GetB(hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
  934. }
  935. }
  936. break;
  937. case FHEXTRA_HTIME:
  938. if (FieldSize>=5)
  939. {
  940. byte Flags=(byte)Raw->GetV();
  941. bool UnixTime=(Flags & FHEXTRA_HTIME_UNIXTIME)!=0;
  942. if ((Flags & FHEXTRA_HTIME_MTIME)!=0)
  943. if (UnixTime)
  944. hd->mtime.SetUnix(Raw->Get4());
  945. else
  946. hd->mtime.SetWin(Raw->Get8());
  947. if ((Flags & FHEXTRA_HTIME_CTIME)!=0)
  948. if (UnixTime)
  949. hd->ctime.SetUnix(Raw->Get4());
  950. else
  951. hd->ctime.SetWin(Raw->Get8());
  952. if ((Flags & FHEXTRA_HTIME_ATIME)!=0)
  953. if (UnixTime)
  954. hd->atime.SetUnix((time_t)Raw->Get4());
  955. else
  956. hd->atime.SetWin(Raw->Get8());
  957. if (UnixTime && (Flags & FHEXTRA_HTIME_UNIX_NS)!=0) // Add nanoseconds.
  958. {
  959. uint ns;
  960. if ((Flags & FHEXTRA_HTIME_MTIME)!=0 && (ns=(Raw->Get4() & 0x3fffffff))<1000000000)
  961. hd->mtime.Adjust(ns);
  962. if ((Flags & FHEXTRA_HTIME_CTIME)!=0 && (ns=(Raw->Get4() & 0x3fffffff))<1000000000)
  963. hd->ctime.Adjust(ns);
  964. if ((Flags & FHEXTRA_HTIME_ATIME)!=0 && (ns=(Raw->Get4() & 0x3fffffff))<1000000000)
  965. hd->atime.Adjust(ns);
  966. }
  967. }
  968. break;
  969. case FHEXTRA_VERSION:
  970. if (FieldSize>=1)
  971. {
  972. Raw->GetV(); // Skip flags field.
  973. uint Version=(uint)Raw->GetV();
  974. if (Version!=0)
  975. {
  976. hd->Version=true;
  977. wchar VerText[20];
  978. swprintf(VerText,ASIZE(VerText),L";%u",Version);
  979. wcsncatz(hd->FileName,VerText,ASIZE(hd->FileName));
  980. }
  981. }
  982. break;
  983. case FHEXTRA_REDIR:
  984. {
  985. hd->RedirType=(FILE_SYSTEM_REDIRECT)Raw->GetV();
  986. uint Flags=(uint)Raw->GetV();
  987. hd->DirTarget=(Flags & FHEXTRA_REDIR_DIR)!=0;
  988. size_t NameSize=(size_t)Raw->GetV();
  989. char UtfName[NM*4];
  990. *UtfName=0;
  991. if (NameSize<ASIZE(UtfName)-1)
  992. {
  993. Raw->GetB(UtfName,NameSize);
  994. UtfName[NameSize]=0;
  995. }
  996. #ifdef _WIN_ALL
  997. UnixSlashToDos(UtfName,UtfName,ASIZE(UtfName));
  998. #endif
  999. UtfToWide(UtfName,hd->RedirName,ASIZE(hd->RedirName));
  1000. }
  1001. break;
  1002. case FHEXTRA_UOWNER:
  1003. {
  1004. uint Flags=(uint)Raw->GetV();
  1005. hd->UnixOwnerNumeric=(Flags & FHEXTRA_UOWNER_NUMUID)!=0;
  1006. hd->UnixGroupNumeric=(Flags & FHEXTRA_UOWNER_NUMGID)!=0;
  1007. *hd->UnixOwnerName=*hd->UnixGroupName=0;
  1008. if ((Flags & FHEXTRA_UOWNER_UNAME)!=0)
  1009. {
  1010. size_t Length=(size_t)Raw->GetV();
  1011. Length=Min(Length,ASIZE(hd->UnixOwnerName)-1);
  1012. Raw->GetB(hd->UnixOwnerName,Length);
  1013. hd->UnixOwnerName[Length]=0;
  1014. }
  1015. if ((Flags & FHEXTRA_UOWNER_GNAME)!=0)
  1016. {
  1017. size_t Length=(size_t)Raw->GetV();
  1018. Length=Min(Length,ASIZE(hd->UnixGroupName)-1);
  1019. Raw->GetB(hd->UnixGroupName,Length);
  1020. hd->UnixGroupName[Length]=0;
  1021. }
  1022. #ifdef _UNIX
  1023. if (hd->UnixOwnerNumeric)
  1024. hd->UnixOwnerID=(uid_t)Raw->GetV();
  1025. if (hd->UnixGroupNumeric)
  1026. hd->UnixGroupID=(gid_t)Raw->GetV();
  1027. #else
  1028. // Need these fields in Windows too for 'list' command,
  1029. // but uid_t and gid_t are not defined.
  1030. if (hd->UnixOwnerNumeric)
  1031. hd->UnixOwnerID=(uint)Raw->GetV();
  1032. if (hd->UnixGroupNumeric)
  1033. hd->UnixGroupID=(uint)Raw->GetV();
  1034. #endif
  1035. hd->UnixOwnerSet=true;
  1036. }
  1037. break;
  1038. case FHEXTRA_SUBDATA:
  1039. {
  1040. // RAR 5.21 and earlier set FHEXTRA_SUBDATA size to 1 less than
  1041. // required. It did not hurt extraction, because UnRAR 5.21
  1042. // and earlier ignored this field and set FieldSize as data left
  1043. // in entire extra area. But now we set the correct field size
  1044. // and set FieldSize based on the actual extra record size,
  1045. // so we need to adjust it for those older archives here.
  1046. // FHEXTRA_SUBDATA in those archives always belongs to HEAD_SERVICE
  1047. // and always is last in extra area. So since its size is by 1
  1048. // less than needed, we always have 1 byte left in extra area,
  1049. // which fact we use here to detect such archives.
  1050. if (bb->HeaderType==HEAD_SERVICE && Raw->Size()-NextPos==1)
  1051. FieldSize++;
  1052. // We cannot allocate too much memory here, because above
  1053. // we check FieldSize againt Raw size and we control that Raw size
  1054. // is sensible when reading headers.
  1055. hd->SubData.Alloc((size_t)FieldSize);
  1056. Raw->GetB(hd->SubData.Addr(0),(size_t)FieldSize);
  1057. }
  1058. break;
  1059. }
  1060. }
  1061. Raw->SetPos(NextPos);
  1062. }
  1063. }
  1064. #ifndef SFX_MODULE
  1065. size_t Archive::ReadHeader14()
  1066. {
  1067. RawRead Raw(this);
  1068. if (CurBlockPos<=(int64)SFXSize)
  1069. {
  1070. Raw.Read(SIZEOF_MAINHEAD14);
  1071. MainHead.Reset();
  1072. byte Mark[4];
  1073. Raw.GetB(Mark,4);
  1074. uint HeadSize=Raw.Get2();
  1075. if (HeadSize<7)
  1076. return false;
  1077. byte Flags=Raw.Get1();
  1078. NextBlockPos=CurBlockPos+HeadSize;
  1079. CurHeaderType=HEAD_MAIN;
  1080. Volume=(Flags & MHD_VOLUME)!=0;
  1081. Solid=(Flags & MHD_SOLID)!=0;
  1082. Locked=(Flags & MHD_LOCK)!=0;
  1083. MainHead.CommentInHeader=(Flags & MHD_COMMENT)!=0;
  1084. MainHead.PackComment=(Flags & MHD_PACK_COMMENT)!=0;
  1085. }
  1086. else
  1087. {
  1088. Raw.Read(SIZEOF_FILEHEAD14);
  1089. FileHead.Reset();
  1090. FileHead.HeaderType=HEAD_FILE;
  1091. FileHead.DataSize=Raw.Get4();
  1092. FileHead.UnpSize=Raw.Get4();
  1093. FileHead.FileHash.Type=HASH_RAR14;
  1094. FileHead.FileHash.CRC32=Raw.Get2();
  1095. FileHead.HeadSize=Raw.Get2();
  1096. if (FileHead.HeadSize<21)
  1097. return false;
  1098. uint FileTime=Raw.Get4();
  1099. FileHead.FileAttr=Raw.Get1();
  1100. FileHead.Flags=Raw.Get1()|LONG_BLOCK;
  1101. FileHead.UnpVer=(Raw.Get1()==2) ? 13 : 10;
  1102. size_t NameSize=Raw.Get1();
  1103. FileHead.Method=Raw.Get1();
  1104. FileHead.SplitBefore=(FileHead.Flags & LHD_SPLIT_BEFORE)!=0;
  1105. FileHead.SplitAfter=(FileHead.Flags & LHD_SPLIT_AFTER)!=0;
  1106. FileHead.Encrypted=(FileHead.Flags & LHD_PASSWORD)!=0;
  1107. FileHead.CryptMethod=FileHead.Encrypted ? CRYPT_RAR13:CRYPT_NONE;
  1108. FileHead.PackSize=FileHead.DataSize;
  1109. FileHead.WinSize=0x10000;
  1110. FileHead.Dir=(FileHead.FileAttr & 0x10)!=0;
  1111. FileHead.HostOS=HOST_MSDOS;
  1112. FileHead.HSType=HSYS_WINDOWS;
  1113. FileHead.mtime.SetDos(FileTime);
  1114. Raw.Read(NameSize);
  1115. char FileName[NM];
  1116. size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
  1117. Raw.GetB((byte *)FileName,ReadNameSize);
  1118. FileName[ReadNameSize]=0;
  1119. IntToExt(FileName,FileName,ASIZE(FileName));
  1120. CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
  1121. ConvertNameCase(FileHead.FileName);
  1122. ConvertFileHeader(&FileHead);
  1123. if (Raw.Size()!=0)
  1124. NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
  1125. CurHeaderType=HEAD_FILE;
  1126. }
  1127. return NextBlockPos>CurBlockPos ? Raw.Size() : 0;
  1128. }
  1129. #endif
  1130. #ifndef SFX_MODULE
  1131. void Archive::ConvertNameCase(wchar *Name)
  1132. {
  1133. if (Cmd->ConvertNames==NAMES_UPPERCASE)
  1134. wcsupper(Name);
  1135. if (Cmd->ConvertNames==NAMES_LOWERCASE)
  1136. wcslower(Name);
  1137. }
  1138. #endif
  1139. bool Archive::IsArcDir()
  1140. {
  1141. return FileHead.Dir;
  1142. }
  1143. void Archive::ConvertAttributes()
  1144. {
  1145. #if defined(_WIN_ALL) || defined(_EMX)
  1146. if (FileHead.HSType!=HSYS_WINDOWS)
  1147. FileHead.FileAttr=FileHead.Dir ? 0x10 : 0x20;
  1148. #endif
  1149. #ifdef _UNIX
  1150. // umask defines which permission bits must not be set by default
  1151. // when creating a file or directory. The typical default value
  1152. // for the process umask is S_IWGRP | S_IWOTH (octal 022),
  1153. // resulting in 0644 mode for new files.
  1154. // Normally umask is applied automatically when creating a file,
  1155. // but we set attributes with chmod later, so we need to calculate
  1156. // resulting attributes here. We do it only for non-Unix archives.
  1157. // We restore native Unix attributes as is, because it can be backup.
  1158. static mode_t mask = (mode_t) -1;
  1159. if (mask == (mode_t) -1)
  1160. {
  1161. // umask call returns the current umask value. Argument (022) is not
  1162. // really important here.
  1163. mask = umask(022);
  1164. // Restore the original umask value, which was changed to 022 above.
  1165. umask(mask);
  1166. }
  1167. switch(FileHead.HSType)
  1168. {
  1169. case HSYS_WINDOWS:
  1170. {
  1171. // Mapping MSDOS, OS/2 and Windows file attributes to Unix.
  1172. if (FileHead.FileAttr & 0x10) // FILE_ATTRIBUTE_DIRECTORY
  1173. {
  1174. // For directories we use 0777 mask.
  1175. FileHead.FileAttr=0777 & ~mask;
  1176. }
  1177. else
  1178. if (FileHead.FileAttr & 1) // FILE_ATTRIBUTE_READONLY
  1179. {
  1180. // For read only files we use 0444 mask with 'w' bits turned off.
  1181. FileHead.FileAttr=0444 & ~mask;
  1182. }
  1183. else
  1184. {
  1185. // umask does not set +x for regular files, so we use 0666
  1186. // instead of 0777 as for directories.
  1187. FileHead.FileAttr=0666 & ~mask;
  1188. }
  1189. }
  1190. break;
  1191. case HSYS_UNIX:
  1192. break;
  1193. default:
  1194. if (FileHead.Dir)
  1195. FileHead.FileAttr=0x41ff & ~mask;
  1196. else
  1197. FileHead.FileAttr=0x81b6 & ~mask;
  1198. break;
  1199. }
  1200. #endif
  1201. }
  1202. void Archive::ConvertFileHeader(FileHeader *hd)
  1203. {
  1204. if (hd->HSType==HSYS_UNKNOWN)
  1205. if (hd->Dir)
  1206. hd->FileAttr=0x10;
  1207. else
  1208. hd->FileAttr=0x20;
  1209. #ifdef _WIN_ALL
  1210. if (hd->HSType==HSYS_UNIX) // Convert Unix, OS X and Android decomposed chracters to Windows precomposed.
  1211. ConvertToPrecomposed(hd->FileName,ASIZE(hd->FileName));
  1212. #endif
  1213. for (wchar *s=hd->FileName;*s!=0;s++)
  1214. {
  1215. #ifdef _UNIX
  1216. // Backslash is the invalid character for Windows file headers,
  1217. // but it can present in Unix file names extracted in Unix.
  1218. if (*s=='\\' && Format==RARFMT50 && hd->HSType==HSYS_WINDOWS)
  1219. *s='_';
  1220. #endif
  1221. #if defined(_WIN_ALL) || defined(_EMX)
  1222. // RAR 5.0 archives do not use '\' as path separator, so if we see it,
  1223. // it means that it is a part of Unix file name, which we cannot
  1224. // extract in Windows.
  1225. if (*s=='\\' && Format==RARFMT50)
  1226. *s='_';
  1227. // ':' in file names is allowed in Unix, but not in Windows.
  1228. // Even worse, file data will be written to NTFS stream on NTFS,
  1229. // so automatic name correction on file create error in extraction
  1230. // routine does not work. In Windows and DOS versions we better
  1231. // replace ':' now.
  1232. if (*s==':')
  1233. *s='_';
  1234. #endif
  1235. // This code must be performed only after other path separator checks,
  1236. // because it produces backslashes illegal for some of checks above.
  1237. // Backslash is allowed in file names in Unix, but not in Windows.
  1238. // Still, RAR 4.x uses backslashes as path separator even in Unix.
  1239. // Forward slash is not allowed in both systems. In RAR 5.0 we use
  1240. // the forward slash as universal path separator.
  1241. if (*s=='/' || *s=='\\' && Format!=RARFMT50)
  1242. *s=CPATHDIVIDER;
  1243. }
  1244. }
  1245. int64 Archive::GetStartPos()
  1246. {
  1247. int64 StartPos=SFXSize+MarkHead.HeadSize;
  1248. if (Format==RARFMT15)
  1249. StartPos+=MainHead.HeadSize;
  1250. else // RAR 5.0.
  1251. StartPos+=CryptHead.HeadSize+FullHeaderSize(MainHead.HeadSize);
  1252. return StartPos;
  1253. }
  1254. bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode)
  1255. {
  1256. if (BrokenHeader)
  1257. {
  1258. uiMsg(UIERROR_SUBHEADERBROKEN,FileName);
  1259. ErrHandler.SetErrorCode(RARX_CRC);
  1260. return false;
  1261. }
  1262. if (SubHead.Method>5 || SubHead.UnpVer>(Format==RARFMT50 ? VER_UNPACK5:VER_UNPACK))
  1263. {
  1264. uiMsg(UIERROR_SUBHEADERUNKNOWN,FileName);
  1265. return false;
  1266. }
  1267. if (SubHead.PackSize==0 && !SubHead.SplitAfter)
  1268. return true;
  1269. SubDataIO.Init();
  1270. Unpack Unpack(&SubDataIO);
  1271. Unpack.Init(SubHead.WinSize,false);
  1272. if (DestFile==NULL)
  1273. {
  1274. if (SubHead.UnpSize>0x1000000)
  1275. {
  1276. // So huge allocation must never happen in valid archives.
  1277. uiMsg(UIERROR_SUBHEADERUNKNOWN,FileName);
  1278. return false;
  1279. }
  1280. if (UnpData==NULL)
  1281. SubDataIO.SetTestMode(true);
  1282. else
  1283. {
  1284. UnpData->Alloc((size_t)SubHead.UnpSize);
  1285. SubDataIO.SetUnpackToMemory(&(*UnpData)[0],(uint)SubHead.UnpSize);
  1286. }
  1287. }
  1288. if (SubHead.Encrypted)
  1289. if (Cmd->Password.IsSet())
  1290. SubDataIO.SetEncryption(false,SubHead.CryptMethod,&Cmd->Password,
  1291. SubHead.SaltSet ? SubHead.Salt:NULL,SubHead.InitV,
  1292. SubHead.Lg2Count,SubHead.HashKey,SubHead.PswCheck);
  1293. else
  1294. return false;
  1295. SubDataIO.UnpHash.Init(SubHead.FileHash.Type,1);
  1296. SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
  1297. SubDataIO.EnableShowProgress(false);
  1298. SubDataIO.SetFiles(this,DestFile);
  1299. SubDataIO.SetTestMode(TestMode);
  1300. SubDataIO.UnpVolume=SubHead.SplitAfter;
  1301. SubDataIO.SetSubHeader(&SubHead,NULL);
  1302. Unpack.SetDestSize(SubHead.UnpSize);
  1303. if (SubHead.Method==0)
  1304. CmdExtract::UnstoreFile(SubDataIO,SubHead.UnpSize);
  1305. else
  1306. Unpack.DoUnpack(SubHead.UnpVer,false);
  1307. if (!SubDataIO.UnpHash.Cmp(&SubHead.FileHash,SubHead.UseHashKey ? SubHead.HashKey:NULL))
  1308. {
  1309. uiMsg(UIERROR_SUBHEADERDATABROKEN,FileName,SubHead.FileName);
  1310. ErrHandler.SetErrorCode(RARX_CRC);
  1311. if (UnpData!=NULL)
  1312. UnpData->Reset();
  1313. return false;
  1314. }
  1315. return true;
  1316. }