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 \
libarchive/test/test_read_format_rar_subblock.rar.uu \
libarchive/test/test_read_format_rar_unicode.rar.uu \
libarchive/test/test_read_format_rar_windows.rar.uu \
+ libarchive/test/test_read_format_rar4_encrypted.rar.uu \
+ libarchive/test/test_read_format_rar4_encrypted_filenames.rar.uu \
+ libarchive/test/test_read_format_rar4_solid_encrypted.rar.uu \
+ libarchive/test/test_read_format_rar4_solid_encrypted_filenames.rar.uu \
+ libarchive/test/test_read_format_rar5_encrypted.rar.uu \
+ libarchive/test/test_read_format_rar5_encrypted_filenames.rar.uu \
+ libarchive/test/test_read_format_rar5_solid_encrypted.rar.uu \
+ libarchive/test/test_read_format_rar5_solid_encrypted_filenames.rar.uu \
libarchive/test/test_read_format_rar5_arm.rar.uu \
libarchive/test/test_read_format_rar5_blake2.rar.uu \
libarchive/test/test_read_format_rar5_compressed.rar.uu \
or just a part of it. */
uint8_t block_parsing_finished : 1;
- signed int notused : 4;
+ /* Flag used to indicate that a previous file using this buffer was
+ encrypted, meaning no data in the buffer can be trusted */
+ uint8_t data_encrypted : 1;
+
+ signed int notused : 3;
int flags; /* Uncompression flags. */
int method; /* Uncompression algorithm method. */
/* 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;
+ int headers_are_encrypted;
};
/* Forward function declarations. */
if(!read_var(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;
&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;
+ rar->cstate.data_encrypted = 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)) {
+ return ARCHIVE_EOF;
+ }
}
}
rar->file.solid = (compression_info & SOLID) > 0;
/* Archives which declare solid files without initializing the window
- * buffer first are invalid. */
+ * buffer first are invalid, unless previous data was encrypted, in
+ * which case we may never have had the chance */
- if(rar->file.solid > 0 && rar->cstate.window_buf == NULL) {
+ if(rar->file.solid > 0 && rar->cstate.data_encrypted == 0 &&
+ rar->cstate.window_buf == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Declared solid file, but no window buffer "
"initialized yet.");
return ARCHIVE_FATAL;
}
}
+ else
+ rar->cstate.data_encrypted = 0; /* Reset for new buffer */
if(rar->cstate.window_size < (ssize_t) window_size &&
rar->cstate.window_buf)
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;
+ rar->headers_are_encrypted = 1;
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Encryption is not supported");
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;
+ }
+
if(rar->header_initialized == 0) {
init_header(a);
if ((ret = try_skip_sfx(a)) < ARCHIVE_WARN)
if (size)
*size = 0;
+ if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
+ rar->has_encrypted_entries = 0;
+ }
+
+ if (rar->headers_are_encrypted || rar->cstate.data_encrypted) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Reading encrypted data is not currently supported");
+ return ARCHIVE_FATAL;
+ }
+
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
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->cstate.data_encrypted == 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 data withing this solid block is
+ * not encrypted, in which case we'll skip and fail if the user
+ * tries to read data. */
int ret;
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) {
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;
}
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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+/*\r
+ * Copyright (c) 2003-2018\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer\r
+ * in this position and unchanged.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR\r
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#include "test.h"\r
+\r
+/*\r
+ * All of the archives for this teset contain four files: a.txt, b.txt, c.txt, and d.txt\r
+ * For solid archives or archvies or archives where filenames are encrypted, all four files are encrypted with the\r
+ * password "password". For non-solid archives without filename encryption, a.txt and c.txt are not encrypted, b.txt is\r
+ * encrypted with the password "password", and d.txt is encrypted with the password "password2".\r
+ *\r
+ * For all files the file contents is "This is from <filename>" (i.e. "This is from a.txt" etc.)\r
+ */\r
+static void test_encrypted_rar_archive(const char *filename, int filenamesEncrypted, int solid)\r
+{\r
+ struct archive_entry *ae;\r
+ struct archive *a;\r
+ char buff[128];\r
+ int expected_read_header_result, expected_read_data_result;\r
+ const int expected_file_size = 18; /* This is from X.txt */\r
+\r
+ /* We should only ever fail to read the header when filenames are encrypted. Otherwise we're failing for other\r
+ * unsupported reasons, in which case we have no hope of detecting encryption */\r
+ expected_read_header_result = filenamesEncrypted ? ARCHIVE_FATAL : ARCHIVE_OK;\r
+\r
+ /* We should only ever fail to read the data for "a.txt" and "c.txt" if they are encrypted */\r
+ /* NOTE: We'll never attempt this when filenames are encrypted, so we only check for solid here */\r
+ expected_read_data_result = solid ? ARCHIVE_FATAL : expected_file_size;\r
+\r
+ extract_reference_file(filename);\r
+ assert((a = archive_read_new()) != NULL);\r
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));\r
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));\r
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, filename, 10240));\r
+\r
+ /* No data read yet; encryption unknown */\r
+ assertEqualInt(ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a));\r
+\r
+ /* Read the header for "a.txt" */\r
+ assertEqualIntA(a, expected_read_header_result, archive_read_next_header(a, &ae));\r
+ if (!filenamesEncrypted) {\r
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));\r
+ assertEqualString("a.txt", archive_entry_pathname(ae));\r
+ assertEqualInt(expected_file_size, archive_entry_size(ae));\r
+ assertEqualInt(solid, archive_entry_is_data_encrypted(ae));\r
+ assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));\r
+ /* NOTE: The reader will set this value to zero on the first header that it reads, even if later entries\r
+ * are encrypted */\r
+ assertEqualInt(solid, archive_read_has_encrypted_entries(a));\r
+ assertEqualIntA(a, expected_read_data_result, archive_read_data(a, buff, sizeof(buff)));\r
+ if (!solid) {\r
+ assertEqualMem("This is from a.txt", buff, expected_file_size);\r
+ }\r
+ }\r
+ else {\r
+ assertEqualInt(1, archive_entry_is_data_encrypted(ae));\r
+ assertEqualInt(1, archive_entry_is_metadata_encrypted(ae));\r
+ assertEqualInt(1, archive_read_has_encrypted_entries(a));\r
+ assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff)));\r
+\r
+ /* Additional attempts to read headers are futile */\r
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));\r
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));\r
+ return;\r
+ }\r
+\r
+ /* From here on out, we can assume that !filenamesEncrypted */\r
+\r
+ /* Read the header for "b.txt" */\r
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));\r
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));\r
+ assertEqualString("b.txt", archive_entry_pathname(ae));\r
+ assertEqualInt(expected_file_size, archive_entry_size(ae));\r
+ assertEqualInt(1, archive_entry_is_data_encrypted(ae));\r
+ assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));\r
+ assertEqualInt(1, archive_read_has_encrypted_entries(a));\r
+ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff)));\r
+\r
+ /* Read the header for "c.txt" */\r
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));\r
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));\r
+ assertEqualString("c.txt", archive_entry_pathname(ae));\r
+ assertEqualInt(expected_file_size, archive_entry_size(ae));\r
+ assertEqualInt(solid, archive_entry_is_data_encrypted(ae));\r
+ assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));\r
+ /* After setting to true above, this should forever be true */\r
+ assertEqualInt(1, archive_read_has_encrypted_entries(a));\r
+ assertEqualIntA(a, expected_read_data_result, archive_read_data(a, buff, sizeof(buff)));\r
+ if (!solid) {\r
+ assertEqualMem("This is from c.txt", buff, expected_file_size);\r
+ }\r
+\r
+ /* Read the header for "d.txt" */\r
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));\r
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));\r
+ assertEqualString("d.txt", archive_entry_pathname(ae));\r
+ assertEqualInt(expected_file_size, archive_entry_size(ae));\r
+ assertEqualInt(1, archive_entry_is_data_encrypted(ae));\r
+ assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));\r
+ assertEqualInt(1, archive_read_has_encrypted_entries(a));\r
+ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff)));\r
+\r
+ /* End of archive. */\r
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));\r
+\r
+ /* Close the archive. */\r
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));\r
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar4_encrypted)\r
+{\r
+ test_encrypted_rar_archive("test_read_format_rar4_encrypted.rar", 0, 0);\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar4_encrypted_filenames)\r
+{\r
+ test_encrypted_rar_archive("test_read_format_rar4_encrypted_filenames.rar", 1, 0);\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar4_solid_encrypted)\r
+{\r
+ /* TODO: If solid RAR4 support is ever added, the following should pass */\r
+#if 0\r
+ test_encrypted_rar_archive("test_read_format_rar4_solid_encrypted.rar", 0, 1);\r
+#else\r
+ skipping("RAR4 solid archive support not currently available");\r
+#endif\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar4_solid_encrypted_filenames)\r
+{\r
+ test_encrypted_rar_archive("test_read_format_rar4_solid_encrypted_filenames.rar", 1, 1);\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar5_encrypted)\r
+{\r
+ test_encrypted_rar_archive("test_read_format_rar5_encrypted.rar", 0, 0);\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar5_encrypted_filenames)\r
+{\r
+ test_encrypted_rar_archive("test_read_format_rar5_encrypted_filenames.rar", 1, 0);\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar5_solid_encrypted)\r
+{\r
+ test_encrypted_rar_archive("test_read_format_rar5_solid_encrypted.rar", 0, 1);\r
+}\r
+\r
+DEFINE_TEST(test_read_format_rar5_solid_encrypted_filenames)\r
+{\r
+ test_encrypted_rar_archive("test_read_format_rar5_solid_encrypted_filenames.rar", 1, 1);\r
+}\r
unsigned long crc;
unsigned long compressed_size = 0;
int file_perm = 00644;
+#ifdef HAVE_ZLIB_H
int zip_version = 20;
+#else
+ int zip_version = 10;
+#endif
int zip_compression = 8;
short file_uid = 10, file_gid = 20;
unsigned char *buff, *buffend, *p;