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