1#!/bin/sh
2# Copyright 2009 by Denys Vlasenko
3# Licensed under GPLv2, see file LICENSE in this source tree.
4
5. ./testing.sh
6test -f "$bindir/.config" && . "$bindir/.config"
7
8unset LANG
9unset LANGUAGE
10unset LC_COLLATE
11unset LC_ALL
12umask 022
13
14# testing "test name" "script" "expected result" "file input" "stdin"
15
16testing "tar Empty file is not a tarball" '\
17tar xvf - 2>&1; echo $?
18' "\
19tar: short read
201
21" \
22"" ""
23SKIP=
24
25optional FEATURE_SEAMLESS_GZ GUNZIP
26# In NOMMU case, "invalid magic" message comes from gunzip child process.
27# Otherwise, it comes from tar.
28# Need to fix output up to avoid false positive.
29testing "tar Empty file is not a tarball.tar.gz" '\
30{ tar xvzf - 2>&1; echo $?; } | grep -Fv "invalid magic"
31' "\
32tar: short read
331
34" \
35"" ""
36SKIP=
37
38testing "tar Two zeroed blocks is a ('truncated') empty tarball" '\
39dd if=/dev/zero bs=512 count=2 2>/dev/null | tar xvf - 2>&1; echo $?
40' "\
410
42" \
43"" ""
44SKIP=
45
46testing "tar Twenty zeroed blocks is an empty tarball" '\
47dd if=/dev/zero bs=512 count=20 2>/dev/null | tar xvf - 2>&1; echo $?
48' "\
490
50" \
51"" ""
52SKIP=
53
54mkdir tar.tempdir && cd tar.tempdir || exit 1
55# "tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input":
56# GNU tar 1.26 records as hardlinks:
57#  input_hard2 -> input_hard1
58#  input_hard1 -> input_hard1 (!!!)
59#  input_dir/file -> input_dir/file
60#  input -> input
61# As of 1.24.0, we don't record last two: for them, nlink==1
62# and we check for "hardlink"ness only files with nlink!=1
63# We also don't use "hrw-r--r--" notation for hardlinks in "tar tv" listing.
64optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
65testing "tar hardlinks and repeated files" '\
66>input_hard1
67ln input_hard1 input_hard2
68mkdir input_dir
69>input_dir/file
70chmod -R 644 *
71chmod    755 input_dir
72tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input
73tar tvf test.tar | sed "s/.*[0-9] input/input/"
74rm -rf input_dir
75tar xf test.tar 2>&1
76echo Ok: $?
77ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
78' "\
79input
80input_dir/
81input_dir/file
82input_hard1
83input_hard2 -> input_hard1
84input_hard1 -> input_hard1
85input_dir/
86input_dir/file
87input
88Ok: 0
89-rw-r--r-- input_dir/file
90drwxr-xr-x input_dir
91-rw-r--r-- input_hard1
92-rw-r--r-- input_hard2
93" \
94"" ""
95SKIP=
96cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
97
98mkdir tar.tempdir && cd tar.tempdir || exit 1
99optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
100testing "tar hardlinks mode" '\
101>input_hard1
102chmod 741 input_hard1
103ln input_hard1 input_hard2
104mkdir input_dir
105ln input_hard1 input_dir
106ln input_hard2 input_dir
107chmod 550 input_dir
108# On some filesystems, input_dir/input_hard2 is returned by readdir
109# BEFORE input_dir/input_hard1! Thats why we cant just "tar cf ... input_*":
110tar cf test.tar input_dir/input_hard* input_hard*
111tar tvf test.tar | sed "s/.*[0-9] input/input/"
112chmod 770 input_dir
113rm -rf input_*
114tar xf test.tar 2>&1
115echo Ok: $?
116ls -l . input_dir/* | grep "input.*hard" | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
117' "\
118input_dir/input_hard1
119input_dir/input_hard2 -> input_dir/input_hard1
120input_hard1 -> input_dir/input_hard1
121input_hard2 -> input_dir/input_hard1
122Ok: 0
123-rwxr----x input_dir/input_hard1
124-rwxr----x input_dir/input_hard2
125-rwxr----x input_hard1
126-rwxr----x input_hard2
127" \
128"" ""
129SKIP=
130cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
131
132mkdir tar.tempdir && cd tar.tempdir || exit 1
133optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
134testing "tar symlinks mode" '\
135>input_file
136chmod 741 input_file
137ln -s input_file input_soft
138mkdir input_dir
139ln input_file input_dir
140ln input_soft input_dir
141chmod 550 input_dir
142tar cf test.tar input_dir/* input_[fs]*
143tar tvf test.tar | sed "s/.*[0-9] input/input/" | sort
144chmod 770 input_dir
145rm -rf input_*
146tar xf test.tar 2>&1
147echo Ok: $?
148ls -l . input_dir/* | grep "input_[fs]" | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
149' "\
150input_dir/input_file
151input_dir/input_soft -> input_file
152input_file -> input_dir/input_file
153input_soft -> input_dir/input_soft
154Ok: 0
155-rwxr----x input_dir/input_file
156lrwxrwxrwx input_file
157-rwxr----x input_file
158lrwxrwxrwx input_file
159" \
160"" ""
161SKIP=
162cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
163
164mkdir tar.tempdir && cd tar.tempdir || exit 1
165optional FEATURE_TAR_CREATE FEATURE_TAR_LONG_OPTIONS
166testing "tar --overwrite" "\
167ln input input_hard
168tar cf test.tar input_hard
169echo WRONG >input
170# --overwrite opens 'input_hard' without unlinking,
171# thus 'input_hard' still linked to 'input' and we write 'Ok' into it
172tar xf test.tar --overwrite 2>&1 && cat input
173" "\
174Ok
175" \
176"Ok\n" ""
177SKIP=
178cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
179
180mkdir tar.tempdir && cd tar.tempdir || exit 1
181test x"$SKIP_KNOWN_BUGS" = x"" && {
182# Needs to be run under non-root for meaningful test
183optional FEATURE_TAR_CREATE
184testing "tar writing into read-only dir" '\
185mkdir input_dir
186>input_dir/input_file
187chmod 550 input_dir
188tar cf test.tar input_dir
189tar tvf test.tar | sed "s/.*[0-9] input/input/"
190chmod 770 input_dir
191rm -rf input_*
192tar xf test.tar 2>&1
193echo Ok: $?
194ls -l input_dir/* . | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
195chmod 770 input_dir
196' "\
197input_dir/
198input_dir/input_file
199Ok: 0
200-rw-r--r-- input_dir/input_file
201dr-xr-x--- input_dir
202" \
203"" ""
204SKIP=
205}
206cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
207
208mkdir tar.tempdir && cd tar.tempdir || exit 1
209# Had a bug where on extract autodetect first "switched off" -z
210# and then failed to recognize .tgz extension
211optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ GUNZIP
212testing "tar extract tgz" "\
213dd count=1 bs=1M if=/dev/zero of=F0 2>/dev/null
214tar -czf F0.tgz F0
215rm F0
216tar -xzvf F0.tgz && echo Ok
217rm F0 || echo BAD
218" "\
219F0
220Ok
221" \
222"" ""
223SKIP=
224cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
225
226mkdir tar.tempdir && cd tar.tempdir || exit 1
227# Do we detect XZ-compressed data (even w/o .tar.xz or txz extension)?
228# (the uuencoded hello_world.txz contains one empty file named "hello_world")
229optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_XZ
230testing "tar extract txz" "\
231uudecode -o input && tar tf input && echo Ok
232" "\
233hello_world
234Ok
235" \
236"" "\
237begin-base64 644 hello_world.txz
238/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AX/AEldADQZSe6ODIZQ3rSQ8kAJ
239SnMPTX+XWGKW3Yu/Rwqg4Ik5wqgQKgVH97J8yA8IvZ4ahaCQogUNHRkXibr2
240Q615wcb2G7fJU49AhWAAAAAAUA8gu9DyXfAAAWWADAAAAB5FXGCxxGf7AgAA
241AAAEWVo=
242====
243"
244SKIP=
245cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
246
247mkdir tar.tempdir && cd tar.tempdir || exit 1
248# On extract, everything up to and including last ".." component is stripped
249optional FEATURE_TAR_CREATE
250testing "tar strips /../ on extract" "\
251rm -rf input_* test.tar 2>/dev/null
252mkdir input_dir
253echo Ok >input_dir/file
254tar cf test.tar ./../tar.tempdir/input_dir/../input_dir 2>&1
255rm -rf input_* 2>/dev/null
256tar -vxf test.tar 2>&1
257cat input_dir/file 2>&1
258" "\
259tar: removing leading './../tar.tempdir/input_dir/../' from member names
260input_dir/
261input_dir/file
262Ok
263" \
264"" ""
265SKIP=
266cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
267
268mkdir tar.tempdir && cd tar.tempdir || exit 1
269# attack.tar.bz2 has symlink pointing to a system file
270# followed by a regular file with the same name
271# containing "root::0:0::/root:/bin/sh":
272#  lrwxrwxrwx root/root passwd -> /tmp/passwd
273#  -rw-r--r-- root/root passwd
274# naive tar implementation may end up creating the symlink
275# and then writing into it.
276# The correct implementation unlinks target before
277# creating the second file.
278# We test that /tmp/passwd remains empty:
279optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
280testing "tar does not extract into symlinks" "\
281>>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
282" "\
283tar: can't create symlink 'passwd' to '/tmp/passwd'
2840
285" \
286"" "\
287begin-base64 644 attack.tar.bz2
288QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
289po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
290DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
291l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
292====
293"
294SKIP=
295cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
296
297mkdir tar.tempdir && cd tar.tempdir || exit 1
298# And same with -k
299optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
300testing "tar -k does not extract into symlinks" "\
301>>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
302" "\
303tar: can't create symlink 'passwd' to '/tmp/passwd'
3040
305" \
306"" "\
307begin-base64 644 attack.tar.bz2
308QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
309po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
310DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
311l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
312====
313"
314SKIP=
315cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
316
317if test x"$CONFIG_UNICODE_USING_LOCALE" != x"y"; then
318mkdir tar.tempdir && cd tar.tempdir || exit 1
319optional UNICODE_SUPPORT FEATURE_TAR_GNU_EXTENSIONS FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT
320testing "tar Pax-encoded UTF8 names and symlinks" '\
321tar xvf ../tar.utf8.tar.bz2 2>&1; echo $?
322export LANG=en_US.UTF-8
323ls -l etc/ssl/certs/* | sed "s:.*etc/:etc/:" | sort
324unset LANG
325rm -rf etc usr
326' "\
327etc/ssl/certs/3b2716e5.0
328etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
329etc/ssl/certs/f80cc7f6.0
330usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt
3310
332etc/ssl/certs/3b2716e5.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
333etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem -> /usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt
334etc/ssl/certs/f80cc7f6.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
335" \
336"" ""
337SKIP=
338cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
339fi
340
341mkdir tar.tempdir && cd tar.tempdir || exit 1
342optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT LS
343testing "tar Symlink attack: create symlink and then write through it" '\
344exec 2>&1
345uudecode -o input && tar xvf input; echo $?
346ls /tmp/bb_test_evilfile
347ls bb_test_evilfile
348ls symlink/bb_test_evilfile
349' "\
350anything.txt
351symlink
352symlink/bb_test_evilfile
353tar: can't create symlink 'symlink' to '/tmp'
3541
355ls: /tmp/bb_test_evilfile: No such file or directory
356ls: bb_test_evilfile: No such file or directory
357symlink/bb_test_evilfile
358" \
359"" "\
360begin-base64 644 tar_symlink_attack.tar.bz2
361QlpoOTFBWSZTWZgs7bQAALT/hMmQAFBAAf+AEMAGJPPv32AAAIAIMAC5thlR
362omAjAmCMADQT1BqNE0AEwAAjAEwElTKeo9NTR6h6gaeoA0DQNLVdwZZ5iNTk
363AQwCAV6S00QFJYhrlfFkVCEDEGtgNVqYrI0uK3ggnt30gqk4e1TTQm5QIAKa
364SJqzRGSFLMmOloHSAcvLiFxxRiQtQZF+qPxbo173ZDISOAoNoPN4PQPhBhKS
365n8fYaKlioCTzL2oXYczyUUIP4u5IpwoSEwWdtoA=
366====
367"
368SKIP=
369cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
370
371mkdir tar.tempdir && cd tar.tempdir || exit 1
372optional FEATURE_TAR_CREATE
373testing "tar Symlinks and hardlinks coexist" '\
374mkdir dir
375>dir/a
376ln -s ../dir/a dir/b
377ln dir/b dir/c
378mkdir new
379tar cf - dir/* | tar -C new -xvf - 2>&1
380' "\
381dir/a
382dir/b
383dir/c
384" \
385"" ""
386SKIP=
387cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
388
389exit $FAILCOUNT
390