1#!/bin/sh
2#
3# Copyright (c) 2008, 2009 Edward Tomasz Napiera��a <trasz@FreeBSD.org>
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
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 AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD: stable/11/tests/sys/acl/aclfuzzer.sh 324404 2017-10-07 23:10:16Z ngie $
28#
29
30# This is an NFSv4 ACL fuzzer.  It expects to be run by non-root in a scratch
31# directory on a filesystem with NFSv4 ACLs support.  Output it generates
32# is expected to be fed to /usr/src/tools/regression/acltools/run script.
33
34NUMBER_OF_COMMANDS=300
35
36run_command()
37{
38	echo "\$ $1"
39	eval $1 2>&1 | sed 's/^/> /'
40}
41
42rnd_from_0_to()
43{
44	max=`expr $1 + 1`
45	rnd=`jot -r 1`
46	rnd=`expr $rnd % $max`
47
48	echo $rnd
49}
50
51rnd_path()
52{
53	rnd=`rnd_from_0_to 3`
54	case $rnd in
55		0) echo "$TMP/aaa" ;;
56		1) echo "$TMP/bbb" ;;
57		2) echo "$TMP/aaa/ccc" ;;
58		3) echo "$TMP/bbb/ddd" ;;
59	esac
60}
61
62f_prepend_random_acl_on()
63{
64	rnd=`rnd_from_0_to 4`
65	case $rnd in
66		0) u="owner@" ;;
67		1) u="group@" ;;
68		2) u="everyone@" ;;
69		3) u="u:1138" ;;
70		4) u="g:1138" ;;
71	esac
72
73	p=""
74	while :; do
75		rnd=`rnd_from_0_to 30`
76		if [ -n "$p" -a $rnd -ge 14 ]; then
77			break;
78		fi
79
80		case $rnd in
81			0) p="${p}r" ;;
82			1) p="${p}w" ;;
83			2) p="${p}x" ;;
84			3) p="${p}p" ;;
85			4) p="${p}d" ;;
86			5) p="${p}D" ;;
87			6) p="${p}a" ;;
88			7) p="${p}A" ;;
89			8) p="${p}R" ;;
90			9) p="${p}W" ;;
91			10) p="${p}R" ;;
92			11) p="${p}c" ;;
93			12) p="${p}C" ;;
94			13) p="${p}o" ;;
95			14) p="${p}s" ;;
96		esac
97	done
98
99	f=""
100	while :; do
101		rnd=`rnd_from_0_to 10`
102		if [ $rnd -ge 6 ]; then
103			break;
104		fi
105
106		case $rnd in
107			0) f="${f}f" ;;
108			1) f="${f}d" ;;
109			2) f="${f}n" ;;
110			3) f="${f}i" ;;
111		esac
112	done
113
114	rnd=`rnd_from_0_to 1`
115	case $rnd in
116		0) x="allow" ;;
117		1) x="deny" ;;
118	esac
119
120	acl="$u:$p:$f:$x"
121
122	file=`rnd_path`
123	run_command "setfacl -a0 $acl $file"
124}
125
126f_getfacl()
127{
128	file=`rnd_path`
129	run_command "getfacl -qn $file"
130}
131
132f_ls_mode()
133{
134	file=`rnd_path`
135	run_command "ls -al $file | sed -n '2p' | cut -d' ' -f1"
136}
137
138f_chmod()
139{
140	b1=`rnd_from_0_to 7`
141	b2=`rnd_from_0_to 7`
142	b3=`rnd_from_0_to 7`
143	b4=`rnd_from_0_to 7`
144	file=`rnd_path`
145
146	run_command "chmod $b1$b2$b3$b4 $file $2"
147}
148
149f_touch()
150{
151	file=`rnd_path`
152	run_command "touch $file"
153}
154
155f_rm()
156{
157	file=`rnd_path`
158	run_command "rm -f $file"
159}
160
161f_mkdir()
162{
163	file=`rnd_path`
164	run_command "mkdir $file"
165}
166
167f_rmdir()
168{
169	file=`rnd_path`
170	run_command "rmdir $file"
171}
172
173f_mv()
174{
175	from=`rnd_path`
176	to=`rnd_path`
177	run_command "mv -f $from $to"
178}
179
180# XXX: To be implemented: chown(8), setting times with touch(1).
181
182switch_to_random_user()
183{
184	# XXX: To be implemented.
185}
186
187execute_random_command()
188{
189	rnd=`rnd_from_0_to 20`
190
191	case $rnd in
192		0|10|11|12|13|15) cmd=f_prepend_random_acl_on ;;
193		1) cmd=f_getfacl ;;
194		2) cmd=f_ls_mode ;;
195		3) cmd=f_chmod ;;
196		4|18|19) cmd=f_touch ;;
197		5) cmd=f_rm ;;
198		6|16|17) cmd=f_mkdir ;;
199		7) cmd=f_rmdir ;;
200		8) cmd=f_mv ;;
201	esac
202
203	$cmd "XXX"
204}
205
206echo "# Fuzzing; will stop after $NUMBER_OF_COMMANDS commands."
207TMP="aclfuzzer_`dd if=/dev/random bs=1k count=1 2>/dev/null | openssl md5`"
208
209run_command "whoami"
210umask 022
211run_command "umask 022"
212run_command "mkdir $TMP"
213
214i=0;
215while [ "$i" -lt "$NUMBER_OF_COMMANDS" ]; do
216	switch_to_random_user
217	execute_random_command
218	i=`expr $i + 1`
219done
220
221run_command "find $TMP -exec setfacl -a0 everyone@:rxd:allow {} \;"
222run_command "rm -rfv $TMP"
223
224echo "# Fuzzed, thank you."
225
226