#!/bin/sh
#
# Copyright (c) 2008, 2009 Edward Tomasz NapieraĆa <trasz@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
# This is an NFSv4 ACL fuzzer. It expects to be run by non-root in a scratch
# directory on a filesystem with NFSv4 ACLs support. Output it generates
# is expected to be fed to /usr/src/tools/regression/acltools/run script.
NUMBER_OF_COMMANDS=300
run_command()
{
echo "\$ $1"
eval $1 2>&1 | sed 's/^/> /'
}
rnd_from_0_to()
{
max=`expr $1 + 1`
rnd=`jot -r 1`
rnd=`expr $rnd % $max`
echo $rnd
}
rnd_path()
{
rnd=`rnd_from_0_to 3`
case $rnd in
0) echo "$TMP/aaa" ;;
1) echo "$TMP/bbb" ;;
2) echo "$TMP/aaa/ccc" ;;
3) echo "$TMP/bbb/ddd" ;;
esac
}
f_prepend_random_acl_on()
{
rnd=`rnd_from_0_to 4`
case $rnd in
0) u="owner@" ;;
1) u="group@" ;;
2) u="everyone@" ;;
3) u="u:1138" ;;
4) u="g:1138" ;;
esac
p=""
while :; do
rnd=`rnd_from_0_to 30`
if [ -n "$p" -a $rnd -ge 14 ]; then
break;
fi
case $rnd in
0) p="${p}r" ;;
1) p="${p}w" ;;
2) p="${p}x" ;;
3) p="${p}p" ;;
4) p="${p}d" ;;
5) p="${p}D" ;;
6) p="${p}a" ;;
7) p="${p}A" ;;
8) p="${p}R" ;;
9) p="${p}W" ;;
10) p="${p}R" ;;
11) p="${p}c" ;;
12) p="${p}C" ;;
13) p="${p}o" ;;
14) p="${p}s" ;;
esac
done
f=""
while :; do
rnd=`rnd_from_0_to 10`
if [ $rnd -ge 6 ]; then
break;
fi
case $rnd in
0) f="${f}f" ;;
1) f="${f}d" ;;
2) f="${f}n" ;;
3) f="${f}i" ;;
esac
done
rnd=`rnd_from_0_to 1`
case $rnd in
0) x="allow" ;;
1) x="deny" ;;
esac
acl="$u:$p:$f:$x"
file=`rnd_path`
run_command "setfacl -a0 $acl $file"
}
f_getfacl()
{
file=`rnd_path`
run_command "getfacl -qn $file"
}
f_ls_mode()
{
file=`rnd_path`
run_command "ls -al $file | sed -n '2p' | cut -d' ' -f1"
}
f_chmod()
{
b1=`rnd_from_0_to 7`
b2=`rnd_from_0_to 7`
b3=`rnd_from_0_to 7`
b4=`rnd_from_0_to 7`
file=`rnd_path`
run_command "chmod $b1$b2$b3$b4 $file $2"
}
f_touch()
{
file=`rnd_path`
run_command "touch $file"
}
f_rm()
{
file=`rnd_path`
run_command "rm -f $file"
}
f_mkdir()
{
file=`rnd_path`
run_command "mkdir $file"
}
f_rmdir()
{
file=`rnd_path`
run_command "rmdir $file"
}
f_mv()
{
from=`rnd_path`
to=`rnd_path`
run_command "mv -f $from $to"
}
# XXX: To be implemented: chown(8), setting times with touch(1).
switch_to_random_user()
{
# XXX: To be implemented.
}
execute_random_command()
{
rnd=`rnd_from_0_to 20`
case $rnd in
0|10|11|12|13|15) cmd=f_prepend_random_acl_on ;;
1) cmd=f_getfacl ;;
2) cmd=f_ls_mode ;;
3) cmd=f_chmod ;;
4|18|19) cmd=f_touch ;;
5) cmd=f_rm ;;
6|16|17) cmd=f_mkdir ;;
7) cmd=f_rmdir ;;
8) cmd=f_mv ;;
esac
$cmd "XXX"
}
echo "# Fuzzing; will stop after $NUMBER_OF_COMMANDS commands."
TMP="aclfuzzer_`dd if=/dev/random bs=1k count=1 2>/dev/null | openssl md5`"
run_command "whoami"
umask 022
run_command "umask 022"
run_command "mkdir $TMP"
i=0;
while [ "$i" -lt "$NUMBER_OF_COMMANDS" ]; do
switch_to_random_user
execute_random_command
i=`expr $i + 1`
done
run_command "find $TMP -exec setfacl -a0 everyone@:rxd:allow {} \;"
run_command "rm -rfv $TMP"
echo "# Fuzzed, thank you."