Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update RAR5 code to report encryption #2096

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ libarchive_test_SOURCES= \
libarchive/test/test_read_format_mtree_crash747.c \
libarchive/test/test_read_format_pax_bz2.c \
libarchive/test/test_read_format_rar.c \
libarchive/test/test_read_format_rar_encryption.c \
libarchive/test/test_read_format_rar_encryption_data.c \
libarchive/test/test_read_format_rar_encryption_partially.c \
libarchive/test/test_read_format_rar_encryption_header.c \
Expand Down
55 changes: 48 additions & 7 deletions libarchive/archive_read_support_format_rar5.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ struct rar5 {
/* The header of currently processed RARv5 block. Used in main
* decompression logic loop. */
struct compressed_block_header last_block_hdr;

/*
* Custom field to denote that this archive contains encrypted entries
*/
int has_encrypted_entries;
};

/* Forward function declarations. */
Expand Down Expand Up @@ -1590,6 +1595,7 @@ static int process_head_file_extra(struct archive_read* a,
if(!read_var_sized(a, &extra_field_id, &var_size))
return ARCHIVE_EOF;

extra_field_size -= var_size;
extra_data_size -= var_size;
if(ARCHIVE_OK != consume(a, var_size)) {
return ARCHIVE_EOF;
Expand Down Expand Up @@ -1617,12 +1623,18 @@ static int process_head_file_extra(struct archive_read* a,
&extra_data_size);
break;
case EX_CRYPT:
/* Mark the entry as encrypted */
archive_entry_set_is_data_encrypted(e, 1);
rar->has_encrypted_entries = 1;
/* fallthrough */
case EX_SUBDATA:
/* fallthrough */
default:
/* Skip unsupported entry. */
return consume(a, extra_data_size);
extra_data_size -= extra_field_size;
if (ARCHIVE_OK != consume(a, extra_field_size)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't actually encounter any errors specific to this code-path, however it made me felt uneasy - e.g. skipping an earlier unsupported field may cause us to skip identifying an encryption field.

return ARCHIVE_EOF;
}
}
}

Expand Down Expand Up @@ -2266,6 +2278,9 @@ static int process_base_block(struct archive_read* a,
ret = process_head_file(a, rar, entry, header_flags);
return ret;
case HEAD_CRYPT:
archive_entry_set_is_metadata_encrypted(entry, 1);
archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1;
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Encryption is not supported");
Expand Down Expand Up @@ -2410,6 +2425,14 @@ static int rar5_read_header(struct archive_read *a,
struct rar5* rar = get_context(a);
int ret;

/*
* It should be sufficient to call archive_read_next_header() for
* a reader to determine if an entry is encrypted or not.
*/
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
}
Comment on lines +2448 to +2450
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something I didn't necessarily like doing, but I copied from other places. Encryption might not necessarily be detected when reading the first header (e.g. if the Nth entry is the first encrypted one), however there's not much difference in practice between perpetually returning ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW and returning 0.


if(rar->header_initialized == 0) {
init_header(a);
if ((ret = try_skip_sfx(a)) < ARCHIVE_WARN)
Expand Down Expand Up @@ -4059,6 +4082,10 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
if (size)
*size = 0;

if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
}
dunhor marked this conversation as resolved.
Show resolved Hide resolved

if(rar->file.dir > 0) {
/* Don't process any data if this file entry was declared
* as a directory. This is needed, because entries marked as
Expand Down Expand Up @@ -4110,11 +4137,14 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
static int rar5_read_data_skip(struct archive_read *a) {
struct rar5* rar = get_context(a);

if(rar->main.solid) {
if(rar->main.solid && (rar->has_encrypted_entries <= 0)) {
/* In solid archives, instead of skipping the data, we need to
* extract it, and dispose the result. The side effect of this
* operation will be setting up the initial window buffer state
* needed to be able to extract the selected file. */
* needed to be able to extract the selected file. Note that
* this is only possible when no entries are encrypted. If any
* entries are encrypted, then we need to just skip the data;
* we'll fail any later attempts to read data from the archive. */

int ret;

Expand Down Expand Up @@ -4189,14 +4219,19 @@ static int rar5_cleanup(struct archive_read *a) {

static int rar5_capabilities(struct archive_read * a) {
(void) a;
return 0;
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
}

static int rar5_has_encrypted_entries(struct archive_read *_a) {
(void) _a;
if (_a && _a->format) {
struct rar5 *rar = (struct rar5 *)_a->format->data;
if (rar) {
return rar->has_encrypted_entries;
}
}

/* Unsupported for now. */
return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}

static int rar5_init(struct rar5* rar) {
Expand All @@ -4205,6 +4240,12 @@ static int rar5_init(struct rar5* rar) {
if(CDE_OK != cdeque_init(&rar->cstate.filters, 8192))
return ARCHIVE_FATAL;

/*
* Until enough data has been read, we cannot tell about
* any encrypted entries yet.
*/
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;

return ARCHIVE_OK;
}

Expand Down
1 change: 1 addition & 0 deletions libarchive/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ IF(ENABLE_TEST)
test_read_format_mtree_crash747.c
test_read_format_pax_bz2.c
test_read_format_rar.c
test_read_format_rar_encryption.c
test_read_format_rar_encryption_data.c
test_read_format_rar_encryption_header.c
test_read_format_rar_encryption_partially.c
Expand Down
10 changes: 10 additions & 0 deletions libarchive/test/test_read_format_rar4_encrypted.rar.uu
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
begin 0744 test_read_format_rar4_encrypted.rar
M4F%R(1H'`,^0<P``#0`````````J8W0@D"H`$@```!(````"56Y:[F17=E@=
M,`4`(````&$N='AT`/#\3!M4:&ES(&ES(&9R;VT@82YT>'1?CG0DE#(`(```
M`!(````"A13ZJ6=7=E@=,P4`(````&(N='ATO@(;FGDJBE4`L'*@-,GY]@T0
M?ZC1UGSKU*2VR-1K@HH>GZZP#?C:ML=$"NKDN\=T()`J`!(````2`````C4]
MFI1N5W98'3`%`"````!C+G1X=`"P/D@M5&AI<R!I<R!F<F]M(&,N='AT[<IT
M))0R`"`````2`````B7ANB9-9'98'3,%`"````!D+G1X=*_B?1/SI5-2`/#[
I88]V^#_)1V@;4"TVC,!XR=.I1:KVB0/<OAC@C&97VP3UZ<0]>P!`!P``
`
end
14 changes: 14 additions & 0 deletions libarchive/test/test_read_format_rar4_encrypted_filenames.rar.uu
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
begin 0744 test_read_format_rar4_encrypted_filenames.rar
M4F%R(1H'`,Z9<X``#0```````````````````'0+AC,H,+6'0#)>8VT<XO:*
M5M'"E1[V+ZKT=VW!$Y2=W$,@Y24Z^"L_;GVG\*4]&"6BQ#?@6TX38EQ\8\4-
M<S5U7JMAF.'L3LOOCM6]\Q60C51S.)^'6MOG_R<DW8EG(```````````(B,(
M]O5[61NCM'\Q9[&<E5D6F6`?WI`#-.(]J?W^C9!U-5O^2='P+5K(ED[:I4T=
M0/ZHVQ[F8HPBZ<+WA.*T5<R$K+8&/OR_\BN8V5VVM]"5F:$4Y:\JR,),%],1
MR;Z>``````````#*B0$)1EIB[[O98],X0DT>H`N+&*.NNPK!]1XJ#(AF_TF6
M0FE3!L0.1T+=I<'X[Z0:F23U_[6S.I:ZNQ.\@HZ\]&0L/P:SA$:,Y<^4.A!\
MSBD7NK5[VE/9$9K/N2`[7]T``````````.\$Z3?>_Z.3*>6<12%741?6_./A
M!:XA!P"B0PS55>+%J)-H$0T!//>$']'-U?_"O=N?_:SNE<^54Z3/[8,M^F?6
M36)XOUNLS4@\\N@1J#Z/V?J<_XS>CNA21,<Q;<;C[@``````````\)]%=^L\
*)-I(DJO^>177HP``
`
end
11 changes: 11 additions & 0 deletions libarchive/test/test_read_format_rar4_solid_encrypted.rar.uu
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
begin 0744 test_read_format_rar4_solid_encrypted.dat
M4F%R(1H'`#O0<P@`#0`````````A873$E#(`,````!(````"56Y:[F17=E@=
M,P4`(````&$N='AT````````````\/Q,&]Q,RV`3V)H10_&#G@'FZ'@$+I%W
MXP?A#XMQ>A-D/\9QH!R+,]AV(8F*MQD3.<V`SC96=-24,@`0````$@````*%
M%/JI9U=V6!TS!0`@````8BYT>'2/%M7(05"L]0"P<J`TBK7M!JH)_:_8K\\K
M,U_X>\,C=-24,@`0````$@````(U/9J4;E=V6!TS!0`@````8RYT>'1ILB:<
M@2)@M@"P/D@MD'UA]R2N^_G@1!L-H?V>K-TV=-24,@`0````$@````(EX;HF
M361V6!TS!0`@````9"YT>'2C+AKDKML%S0#P^V&/?J,L#@>!52=M.=PPCAJF
(IL0]>P!`!P``
`
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
begin 0744 test_read_format_rar4_solid_encrypted_filenames.rar
M4F%R(1H'`#K9<X@`#0```````````````````,L":IWIGA+/YV2@]#O3Z\&O
MM'G1)=DT/G2[DW184@7Z`)NZR=<IA_-5+=&`P_B)U/,]<+8]C:YI<X@;OT`3
M]?.U#K0BV:I"0AYHE-->?V[74Q\@?])NR\68105J4BRL3O.E$I*!91X?$@/<
M5C[G2D$``````````!NS=YISD[7`_=#)$A.9/&9<3`&D$(L]$^-&%;!SH,%>
M!NZ:W\)5XCJI<"H7+BND(033Q/J9/18(=/`A%WI]@(`:H>AE`M3T)R8']S%P
MHYCV```````````&TB\_##3K6#@Q+J)RDEJ0$CI"]*R1)8!Q.3B[,7O5NM,]
ME::7;E__N2:-%4-;/D+DA:J@P.L0*I/__*OX77=\L4-&F^""&L'VP9/DK-;$
MLP``````````1D.3Y0+"D$@9F(IYV&*B<`A2J2$)(C=_X_QEMWE*VK9ITH*U
MAJ@<<Z%4#?(I"H:5J08&7^WM`<#3=A9D#':;X2IVK.%[ZZ#58(4W0Q[RT-X`
7`````````/"?17?K/"3:2)*K_GD5UZ,`
`
end
12 changes: 12 additions & 0 deletions libarchive/test/test_read_format_rar5_encrypted.rar.uu
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
begin 0744 test_read_format_rar5_encrypted.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@``U_S(>'P(#"Q($$B!5;EKN@```!6$N
M='AT"@,"?"&$HX)\V@%4:&ES(&ES(&9R;VT@82YT>'1Z07&S4`(#/#`$$B`8
M1:,"@`,`!6(N='AT,`$``P_'1%[A@/BUG]8K0S<(O%?-^C3?!JM=!=23!W</
M'8Z`4^HU9QUP\2U+:YP:G`H#`G)EF*:"?-H!8[I4LM`0I4E?M+K3P&FH.QN\
MNS@GUX>3>',O?)/BTBC$`-[^IL`[?FQGU`50`-SXC7SQ9A\"`PL2!!(@-3V:
ME(````5C+G1X=`H#`CY(Z:Z"?-H!5&AI<R!I<R!F<F]M(&,N='AT[/WP75("
M`SR@``22`"##WV,2@`,`!60N='AT,`$``P_'1%[A@/BUG]8K0S<(O%?-\\W6
MLQRT6Z=\K#98CK,.:8-,U$CI%>O6K'>WHPH#`GO%*?2/?-H!VVER]/96CJ;]
?&67IE;,VA30W]2J@TR>'LO7!`C+8JEX==U91`P4$````
`
end
19 changes: 19 additions & 0 deletions libarchive/test/test_read_format_rar5_encrypted_filenames.rar.uu
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
begin 0744 test_read_format_rar5_encrypted_filenames.rar
M4F%R(1H'`0"N(]*0(00```$/:`NPT*?(O:'>=*=Q,C2;&;<*@A@[)[D`X\II
M)1#LA,>A'D8M?0XU3L36UDKMZ3EWQ[HCXZ3<%!O*=.Y,W/S<QCA?O/:*,^Z5
M=M6S3*Y6;+35C`9`*4W]<':72F3'&:K>,FBUJV)T^1MW,X0)C4P7W(`"$#-N
MQ\V%/Z&YJ=4A7#WA+9.5'__1CF)4F:?SV[[N1U^16P.+TQ5X.'"@NQ"=6K3Z
M>:;.1CVE<%%M1-OQ3L0FZ[KI2TSW`.2SF20<ZT/,=/(WK4+9"\+J&$')_3V,
MFW%?=^[MI.6[JA/>0V5WTB3-QIV<3Q'?++X$0]?XV(?ER,71CAXBNL1KT5A*
M8*&+T@6]A_)*KA]%V3S,0B;S(LW1V.AH.U6U0N\-%!@J9Q-FJ%^'O)(JR5+2
MS$5JO/XA3W4MSJ[R27%P_4$GAWSW!SS(4IA_-)Z:[:?V5D!F@TGG9L0!1TF[
M:AH<9G0.['%7-\:>"&(8Y#Z#62;U.:,3+=<$E6S8C02I[/<OZ>G>-3P1Y<'J
MW_FJ/]VJ-Q7IA64<?`;GTW<H]@=YS0)S*\?SKXQ$H.Y!<ZK`[1[?Z(\(_\]>
MU:_TK/EHMM;PWJ?3`Y9S6&%6L@T0-U<&4E[+_F>Z%+KFW'&W>`,.=]#SI;A[
MYA);NM6`5K01J]@IT6O8W#!].A$%_5M\E]S0&<D`"T,:H7>.TOPBCL9$C"GU
M2<W)Q\9ABJLH57<$#;&%<^N#-N[5KE?`56,WSHG<GU4!!.+@ZU+5N\;J[7J-
M**R#V\19<I;O[I%?-002U,8R$.^M/P8W]?26N+VB5-\B#7;SV;_L#%4PQ36P
MBTTF>G&8E))@.H01Q:@1Q^.YVYIG(?#2:S604D\'CWU.!:-E`=;4VFS+KULL
KJ<2G@G$-MF5V72TYY!]U(UB473O?`U'=W'#D\4A%S-_F?/@]S)MU>.[V1```
`
end
14 changes: 14 additions & 0 deletions libarchive/test/test_read_format_rar5_solid_encrypted.rar.uu
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
begin 0744 test_read_format_rar5_solid_encrypted.rar
M4F%R(1H'`0`@MOH1"@$%!@0%`0&`@`!A#\6>4@(#/+``!)(`(%5N6NZ`0P`%
M82YT>'0P`0`!#X`.^EM!19`,=C!0B-G+#?0([51UI],+OH^T\:=V\5`OX@\X
M+B?>=W@0'[TD"@,"?"&$HX)\V@$UI92M^>J?V-L?2@`2L023@_#?H\C>K?GG
MDT*27O`>\]$\(4^12SZAD2GI6I(?@NS\ETUG4@(#/)``!)(`(#W[M6/`0P`%
M8BYT>'0P`0`##X`.^EM!19`,=C!0B-G+#?09'G;UMT5!4+;8`6WM=*[?X@\X
M+B?>=W@0'[TD"@,"<F68IH)\V@$C,XZR45`RX*-59&X3Y'+)'7P<"E("`SR0
M``22`"#_)YR&P$,`!6,N='AT,`$``P^`#OI;0460#'8P4(C9RPWT6V3<1-F,
M1I0"0-:R/5=BUN(/."XGWG=X$!^])`H#`CY(Z:Z"?-H!BBA?J'.;?7%L12A&
M0%6=`D>/[#]2`@,\D``$D@`@>Q=TP\!#``5D+G1X=#`!``,/@`[Z6T%%D`QV
M,%"(V<L-]&ES:(+U/SMVI#;?U9:@A&OB#S@N)]YW>!`?O20*`P)[Q2GTCWS:
9`3G@<$3$LKSYCC7DX.K9`[`==U91`P4$````
`
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
begin 0744 test_read_format_rar5_solid_encrypted_filenames.rar
M4F%R(1H'`0";0=T:(00```$/AC5`PSS2$L"IUF$&I":C])K[3<7Y3A09X<`H
M`7''7U?%(MHPZ3W;#Z7PZEC<2`T4N9L0A@JE?=;1"4#J%N#6H+4KYITU<*=Q
MG$W?R7^W[#&LN^@M8(VSG.,@!1JFX359D^5#S[,ZW]V]CJ'J?-Z!KX^]Y1FB
M8I%5/(^2-8V^KY:K1^?K`DVW*MUL>Q9_6`W#,2ST:17"'W'YF2?)NH%5V"_F
M7;[0VI^.\JJ-T,_(\\5#ZX1HVQJ7KU0UCF#FGD-?NRMKA;X<,[/[*94^27X,
M#)I<:BO^_-I%B&A1U>S)9__""\/M>Q5AIY'*]EPTNJW+.J57[$X\U:;W">Z;
M8P\Z0[ZQOI*B*?BJ?B5+(/Z4.4AJ@;()1YUV4+XY#!76WZV]LZ+;GZ_Q#LLP
MP`7??+NV**I(A-9N^7HX\V!+YJ3%;R<PA5#T<.1"/TKRXC6SM=>%MD?Q5&H@
M>$VAME3"U$312+@SF+8F2RR0)T"DG^4N,^P46&+TZKQ7KS`4@-:J%_["UP"(
MK=]N^!UJUO2#6Q*`-`-)^?\/`;^4(@FVLVJ?!D,:O)A6@!TNA%.U^"0-?9H<
M:0&(UWV=+&[82L>'L4XYO20"@)^<WC4/BKMBFP0G&/3,!*[Y+,F),*X7V7]H
M3&`4SIL,>I']_<2C]D;_,]/)_1?N1+M@PTDL;'[J1L=5\,-?J5Q`$3>_9<2<
MS^)#MZ*AE=5@5[O(<]*(EIA62$U`5B18?#W;BB.*0A3O%<OI.7X`?QB-FRV]
M89*8RNH'P\"9I,0X&F;$<0Z70E(,^KF&PZ5WR-O%K;G`"/=E<\4-*H%FZ]O3
8G%A)/>[(IVC3ME2PY5F>9$/U'$VW1-BZ
`
end