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