1 /*
2 * Copyright (c) 2003-2018
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26 #include "test.h"
27
28 /*
29 * All of the archives for this teset contain four files: a.txt, b.txt, c.txt, and d.txt
30 * For solid archives or archvies or archives where filenames are encrypted, all four files are encrypted with the
31 * password "password". For non-solid archives without filename encryption, a.txt and c.txt are not encrypted, b.txt is
32 * encrypted with the password "password", and d.txt is encrypted with the password "password2".
33 *
34 * For all files the file contents is "This is from <filename>" (i.e. "This is from a.txt" etc.)
35 */
test_encrypted_rar_archive(const char * filename,int filenamesEncrypted,int solid)36 static void test_encrypted_rar_archive(const char *filename, int filenamesEncrypted, int solid)
37 {
38 struct archive_entry *ae;
39 struct archive *a;
40 char buff[128];
41 int expected_read_header_result, expected_read_data_result;
42 const int expected_file_size = 18; /* This is from X.txt */
43
44 /* We should only ever fail to read the header when filenames are encrypted. Otherwise we're failing for other
45 * unsupported reasons, in which case we have no hope of detecting encryption */
46 expected_read_header_result = filenamesEncrypted ? ARCHIVE_FATAL : ARCHIVE_OK;
47
48 /* We should only ever fail to read the data for "a.txt" and "c.txt" if they are encrypted */
49 /* NOTE: We'll never attempt this when filenames are encrypted, so we only check for solid here */
50 expected_read_data_result = solid ? ARCHIVE_FATAL : expected_file_size;
51
52 extract_reference_file(filename);
53 assert((a = archive_read_new()) != NULL);
54 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
55 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
56 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, filename, 10240));
57
58 /* No data read yet; encryption unknown */
59 assertEqualInt(ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, archive_read_has_encrypted_entries(a));
60
61 /* Read the header for "a.txt" */
62 assertEqualIntA(a, expected_read_header_result, archive_read_next_header(a, &ae));
63 if (!filenamesEncrypted) {
64 assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
65 assertEqualString("a.txt", archive_entry_pathname(ae));
66 assertEqualInt(expected_file_size, archive_entry_size(ae));
67 assertEqualInt(solid, archive_entry_is_data_encrypted(ae));
68 assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
69 /* NOTE: The reader will set this value to zero on the first header that it reads, even if later entries
70 * are encrypted */
71 assertEqualInt(solid, archive_read_has_encrypted_entries(a));
72 assertEqualIntA(a, expected_read_data_result, archive_read_data(a, buff, sizeof(buff)));
73 if (!solid) {
74 assertEqualMem("This is from a.txt", buff, expected_file_size);
75 }
76 }
77 else {
78 assertEqualInt(1, archive_entry_is_data_encrypted(ae));
79 assertEqualInt(1, archive_entry_is_metadata_encrypted(ae));
80 assertEqualInt(1, archive_read_has_encrypted_entries(a));
81 assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff)));
82
83 /* Additional attempts to read headers are futile */
84 assertEqualInt(ARCHIVE_OK, archive_read_close(a));
85 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
86 return;
87 }
88
89 /* From here on out, we can assume that !filenamesEncrypted */
90
91 /* Read the header for "b.txt" */
92 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
93 assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
94 assertEqualString("b.txt", archive_entry_pathname(ae));
95 assertEqualInt(expected_file_size, archive_entry_size(ae));
96 assertEqualInt(1, archive_entry_is_data_encrypted(ae));
97 assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
98 assertEqualInt(1, archive_read_has_encrypted_entries(a));
99 assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff)));
100
101 /* Read the header for "c.txt" */
102 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
103 assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
104 assertEqualString("c.txt", archive_entry_pathname(ae));
105 assertEqualInt(expected_file_size, archive_entry_size(ae));
106 assertEqualInt(solid, archive_entry_is_data_encrypted(ae));
107 assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
108 /* After setting to true above, this should forever be true */
109 assertEqualInt(1, archive_read_has_encrypted_entries(a));
110 assertEqualIntA(a, expected_read_data_result, archive_read_data(a, buff, sizeof(buff)));
111 if (!solid) {
112 assertEqualMem("This is from c.txt", buff, expected_file_size);
113 }
114
115 /* Read the header for "d.txt" */
116 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
117 assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
118 assertEqualString("d.txt", archive_entry_pathname(ae));
119 assertEqualInt(expected_file_size, archive_entry_size(ae));
120 assertEqualInt(1, archive_entry_is_data_encrypted(ae));
121 assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
122 assertEqualInt(1, archive_read_has_encrypted_entries(a));
123 assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff)));
124
125 /* End of archive. */
126 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
127
128 /* Close the archive. */
129 assertEqualInt(ARCHIVE_OK, archive_read_close(a));
130 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
131 }
132
DEFINE_TEST(test_read_format_rar4_encrypted)133 DEFINE_TEST(test_read_format_rar4_encrypted)
134 {
135 test_encrypted_rar_archive("test_read_format_rar4_encrypted.rar", 0, 0);
136 }
137
DEFINE_TEST(test_read_format_rar4_encrypted_filenames)138 DEFINE_TEST(test_read_format_rar4_encrypted_filenames)
139 {
140 test_encrypted_rar_archive("test_read_format_rar4_encrypted_filenames.rar", 1, 0);
141 }
142
DEFINE_TEST(test_read_format_rar4_solid_encrypted)143 DEFINE_TEST(test_read_format_rar4_solid_encrypted)
144 {
145 /* TODO: If solid RAR4 support is ever added, the following should pass */
146 #if 0
147 test_encrypted_rar_archive("test_read_format_rar4_solid_encrypted.rar", 0, 1);
148 #else
149 skipping("RAR4 solid archive support not currently available");
150 #endif
151 }
152
DEFINE_TEST(test_read_format_rar4_solid_encrypted_filenames)153 DEFINE_TEST(test_read_format_rar4_solid_encrypted_filenames)
154 {
155 test_encrypted_rar_archive("test_read_format_rar4_solid_encrypted_filenames.rar", 1, 1);
156 }
157
DEFINE_TEST(test_read_format_rar5_encrypted)158 DEFINE_TEST(test_read_format_rar5_encrypted)
159 {
160 test_encrypted_rar_archive("test_read_format_rar5_encrypted.rar", 0, 0);
161 }
162
DEFINE_TEST(test_read_format_rar5_encrypted_filenames)163 DEFINE_TEST(test_read_format_rar5_encrypted_filenames)
164 {
165 test_encrypted_rar_archive("test_read_format_rar5_encrypted_filenames.rar", 1, 0);
166 }
167
DEFINE_TEST(test_read_format_rar5_solid_encrypted)168 DEFINE_TEST(test_read_format_rar5_solid_encrypted)
169 {
170 test_encrypted_rar_archive("test_read_format_rar5_solid_encrypted.rar", 0, 1);
171 }
172
DEFINE_TEST(test_read_format_rar5_solid_encrypted_filenames)173 DEFINE_TEST(test_read_format_rar5_solid_encrypted_filenames)
174 {
175 test_encrypted_rar_archive("test_read_format_rar5_solid_encrypted_filenames.rar", 1, 1);
176 }
177