1#!/usr/local/bin/ksh93 -p
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
24# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26
27. $STF_SUITE/tests/acl/acl_common.kshlib
28
29#################################################################################
30#
31# __stc_assertion_start
32#
33# ID: zfs_acl_chmod_owner_001_pos
34#
35# DESCRIPTION:
36#	Verify that the write_owner for
37#	owner/group/everyone are correct.
38#
39# STRATEGY:
40# 1. Create file and  directory in zfs filesystem
41# 2. Set special write_owner ACE to the file and directory
42# 3. Try to chown/chgrp of the file and directory to take owner/group
43# 4. Verify that the owner/group are correct. Follow these rules:
44#  	(1) If uid is granted the write_owner permission,
45#		then it can only do chown to its own uid,
46#		or a group that they are a member of.
47#	(2) Owner will ignore permission of (1) even write_owner not granted.
48#	(3) Superuser will always permit whatever they do.
49#
50# TESTABILITY: explicit
51#
52# TEST_AUTOMATION_LEVEL: automated
53#
54# CODING_STATUS: COMPLETED (2005-10-26)
55#
56# __stc_assertion_end
57#
58################################################################################
59
60verify_runnable "both"
61
62function cleanup
63{
64	[[ ! -e $TESTDIR/$ARCHIVEFILE ]] && return 0
65
66	if [[ ! -e $target ]]; then
67		log_must $TAR xpf $TESTDIR/$ARCHIVEFILE
68	fi
69
70	(( ${#cwd} != 0 )) && cd $cwd
71	cleanup_test_files $TESTDIR/basedir
72	log_must $RM -f $TESTDIR/$ARCHIVEFILE
73	return 0
74}
75
76#owner@	          group                  group_users       other_users
77set -A users \
78"root"            "root"                 "$ZFS_ACL_ADMIN"  "$ZFS_ACL_OTHER1" \
79"$ZFS_ACL_STAFF1" "$ZFS_ACL_STAFF_GROUP" "$ZFS_ACL_STAFF2" "$ZFS_ACL_OTHER1"
80
81set -A a_access \
82	"write_owner:allow" \
83	"write_owner:deny"
84
85set -A a_flag "owner@" "group@" "everyone@"
86
87log_assert "Verify that the chown/chgrp could take owner/group " \
88	"while permission is granted."
89log_onexit cleanup
90
91#
92# Get the owner of a file/directory
93#
94function get_owner #node
95{
96	typeset node=$1
97	typeset value
98
99	if [[ -z $node ]]; then
100		log_fail "node are not defined."
101	fi
102
103	if [[ -d $node ]]; then
104		value=$($LS -dl $node | $AWK '{print $3}')
105	elif [[ -e $node ]]; then
106		value=$($LS -l $node | $AWK '{print $3}')
107	fi
108
109	$ECHO $value
110}
111
112#
113# Get the group of a file/directory
114#
115function get_group #node
116{
117	typeset node=$1
118	typeset value
119
120	if [[ -z $node ]]; then
121		log_fail "node are not defined."
122	fi
123
124	if [[ -d $node ]]; then
125		value=$($LS -dl $node | $AWK '{print $4}')
126	elif [[ -e $node ]]; then
127		value=$($LS -l $node | $AWK '{print $4}')
128	fi
129
130	$ECHO $value
131}
132
133
134#
135# Get the group name that a UID belongs to
136#
137function get_user_group #uid
138{
139	typeset uid=$1
140	typeset value
141
142	if [[ -z $uid ]]; then
143		log_fail "UID not defined."
144	fi
145
146	value=$(id $uid)
147
148	if [[ $? -eq 0 ]]; then
149		value=${value##*\(}
150		value=${value%%\)*}
151		$ECHO $value
152	else
153		log_fail "Invalid UID (uid)."
154	fi
155}
156
157function operate_node_owner #user node old_owner expect_owner
158{
159	typeset user=$1
160	typeset node=$2
161	typeset old_owner=$3
162	typeset expect_owner=$4
163	typeset ret new_owner
164
165	if [[ $user == "" || $node == "" ]]; then
166		log_fail "user, node are not defined."
167	fi
168
169	chgusr_exec $user $CHOWN $expect_owner $node ; ret=$?
170	new_owner=$(get_owner $node)
171
172	if [[ $new_owner != $old_owner ]]; then
173		$TAR xpf $TESTDIR/$ARCHIVEFILE
174	fi
175
176	if [[ $ret -eq 0 ]]; then
177		if [[ $new_owner != $expect_owner ]]; then
178			log_note "Owner not changed as expected " \
179				"($old_owner|$new_owner|$expect_owner), " \
180				"but return code is $ret."
181			return 1
182		fi
183	elif [[ $ret -ne 0 && $new_owner != $old_owner ]]; then
184		log_note "Owner changed ($old_owner|$new_owner), " \
185			"but return code is $ret."
186		return 2
187	fi
188
189	return $ret
190}
191
192function operate_node_group #user node old_group expect_group
193{
194	typeset user=$1
195	typeset node=$2
196	typeset old_group=$3
197	typeset expect_group=$4
198	typeset ret new_group
199
200	if [[ $user == "" || $node == "" ]]; then
201		log_fail "user, node are not defined."
202	fi
203
204	chgusr_exec $user $CHGRP $expect_group $node ; ret=$?
205	new_group=$(get_group $node)
206
207	if [[ $new_group != $old_group ]]; then
208		$TAR xpf $TESTDIR/$ARCHIVEFILE
209	fi
210
211	if [[ $ret -eq 0 ]]; then
212		if [[ $new_group != $expect_group ]]; then
213			log_note "Group not changed as expected " \
214				"($old_group|$new_group|$expect_group), " \
215				"but return code is $ret."
216			return 1
217		fi
218	elif [[ $ret -ne 0 && $new_group != $old_group ]]; then
219		log_note "Group changed ($old_group|$new_group), " \
220			"but return code is $ret."
221		return 2
222	fi
223
224	return $ret
225}
226
227function logname #acl_target user old new
228{
229	typeset acl_target=$1
230	typeset user=$2
231	typeset old=$3
232	typeset new=$4
233	typeset ret="log_mustnot"
234
235	# To super user, read and write deny permission was override.
236	if [[ $user == root ]]; then
237		ret="log_must"
238	elif [[ $user == $new ]] ; then
239		if [[ $user == $old || $acl_target == *:allow ]]; then
240			ret="log_must"
241		fi
242	fi
243
244	print $ret
245}
246
247function check_chmod_results #node flag acl_target g_usr o_usr
248{
249	typeset node=$1
250	typeset flag=$2
251	typeset acl_target=$2:$3
252	typeset g_usr=$4
253	typeset o_usr=$5
254	typeset log old_owner old_group new_owner new_group
255
256	old_owner=$(get_owner $node)
257	old_group=$(get_group $node)
258
259	if [[ $flag == "owner@" || $flag == "everyone@" ]]; then
260		for new_owner in $ZFS_ACL_CUR_USER "nobody"; do
261			new_group=$(get_user_group $new_owner)
262
263			log=$(logname $acl_target $ZFS_ACL_CUR_USER \
264				$old_owner $new_owner)
265
266			$log operate_node_owner $ZFS_ACL_CUR_USER $node \
267				$old_owner $new_owner
268
269			$log operate_node_group $ZFS_ACL_CUR_USER $node \
270				$old_group $new_group
271		done
272	fi
273	if [[ $flag == "group@" || $flag == "everyone@" ]]; then
274		for new_owner in $g_usr "nobody"; do
275			new_group=$(get_user_group $new_owner)
276
277			log=$(logname $acl_target $g_usr $old_owner \
278				$new_owner)
279
280			$log operate_node_owner $g_usr $node \
281				$old_owner $new_owner
282
283			$log operate_node_group $g_usr \
284				$node $old_group $new_group
285		done
286	fi
287	if [[ $flag == "everyone@" ]]; then
288		for new_owner in $g_usr "nobody"; do
289			new_group=$(get_user_group $new_owner)
290
291			log=$(logname $acl_target $o_usr $old_owner \
292				$new_owner)
293
294			$log operate_node_owner $o_usr $node \
295				$old_owner $new_owner
296
297			$log operate_node_group $o_usr $node \
298				$old_group $new_group
299		done
300	fi
301}
302
303function test_chmod_basic_access #node g_usr o_usr
304{
305	typeset node=${1%/}
306	typeset g_usr=$2
307	typeset o_usr=$3
308	typeset flag acl_p acl_t parent
309
310	parent=${node%/*}
311
312	for flag in ${a_flag[@]}; do
313		for acl_t in "${a_access[@]}"; do
314			log_must usr_exec $CHMOD A+$flag:$acl_t $node
315
316			$TAR cpf $TESTDIR/$ARCHIVEFILE basedir
317
318			check_chmod_results "$node" "$flag" \
319				"$acl_t" "$g_usr" "$o_usr"
320
321			log_must usr_exec $CHMOD A0- $node
322		done
323	done
324}
325
326function setup_test_files #base_node user group
327{
328	typeset base_node=$1
329	typeset user=$2
330	typeset group=$3
331
332	cleanup_test_files $base_node
333
334	log_must $MKDIR -p $base_node
335	log_must $CHOWN $user:$group $base_node
336
337	log_must set_cur_usr $user
338
339	# Prepare all files/sub-dirs for testing.
340
341	file0=$base_node/testfile_rm
342
343	dir0=$base_node/testdir_rm
344
345	log_must usr_exec $TOUCH $file0
346	log_must usr_exec $CHMOD 444 $file0
347
348	log_must usr_exec $MKDIR -p $dir0
349	log_must usr_exec $CHMOD 444 $dir0
350
351	log_must usr_exec $CHMOD 555 $base_node
352	return 0
353}
354
355function cleanup_test_files #base_node
356{
357	typeset base_node=$1
358
359	if [[ -d $base_node ]]; then
360		log_must $RM -rf $base_node
361	elif [[ -e $base_node ]]; then
362		log_must $RM -f $base_node
363	fi
364
365	return 0
366}
367
368typeset cwd=$PWD
369typeset ARCHIVEFILE=archive.tar
370
371test_requires ZFS_ACL
372
373typeset -i i=0
374typeset -i j=0
375typeset target
376cd $TESTDIR
377while (( i < ${#users[@]} )); do
378	setup_test_files $TESTDIR/basedir ${users[i]} ${users[((i+1))]}
379
380	j=0
381	while (( j < 1 )); do
382		eval target=\$file$j
383		test_chmod_basic_access $target \
384			"${users[((i+2))]}" "${users[((i+3))]}"
385
386		eval target=\$dir$j
387		test_chmod_basic_access $target \
388			"${users[((i+2))]}" "${users[((i+3))]}"
389
390		(( j = j + 1 ))
391	done
392
393	(( i += 4 ))
394done
395
396log_pass "Verify that the chown/chgrp could take owner/group " \
397	"while permission is granted."
398