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 2008 Sun Microsystems, Inc.  All rights reserved.
27# Use is subject to license terms.
28#
29# ident	"@(#)zfs_acl_chmod_inherit_002_pos.ksh	1.3	08/02/27 SMI"
30#
31
32. $STF_SUITE/tests/acl/acl_common.kshlib
33. $STF_SUITE/tests/acl/cifs/cifs.kshlib
34
35#################################################################################
36#
37# __stc_assertion_start
38#
39# ID: zfs_acl_chmod_inherit_002_pos
40#
41# DESCRIPTION:
42#	Verify chmod have correct behaviour to directory and file when
43#	filesystem has the different aclinherit setting
44#
45# STRATEGY:
46#	1. Loop super user and non-super user to run the test case.
47#	2. Create basedir and a set of subdirectores and files within it.
48#	3. Separately chmod basedir with different inherite options,
49#	 	combine with the variable setting of aclinherit:
50#		"discard", "noallow", "secure" or "passthrough".
51#	4. Then create nested directories and files like the following.
52#
53#                     ofile
54#                     odir
55#          chmod -->  basedir -|
56#                              |_ nfile1
57#                              |_ ndir1 _
58#                                        |_ nfile2
59#                                        |_ ndir2 _
60#                                                  |_ nfile3
61#                                                  |_ ndir3
62#
63#	5. Verify each directories and files have the correct access control
64#	   capability.
65#
66# TESTABILITY: explicit
67#
68# TEST_AUTOMATION_LEVEL: automated
69#
70# CODING_STATUS: COMPLETED (2006-03-02)
71#
72# __stc_assertion_end
73#
74################################################################################
75
76verify_runnable "both"
77
78function cleanup
79{
80	typeset dir
81
82	# Cleanup basedir, compared file and dir.
83
84	if [[ -f $ofile ]]; then
85		log_must $RM -f $ofile
86	fi
87
88	for dir in $odir $basedir ; do
89		if [[ -d $dir ]]; then
90			log_must $RM -rf $dir
91		fi
92	done
93}
94
95log_assert "Verify chmod have correct behaviour to directory and file when " \
96	"filesystem has the different aclinherit setting."
97log_onexit cleanup
98
99# Define inherit flag
100set -A aclinherit_flag discard noallow secure passthrough
101set -A object_flag file_inherit dir_inherit file_inherit/dir_inherit
102set -A strategy_flag "" inherit_only no_propagate inherit_only/no_propagate
103
104typeset ace_prefix1="user:$ZFS_ACL_OTHER1"
105typeset ace_prefix2="user:$ZFS_ACL_OTHER2"
106typeset ace_discard ace_noallow ace_secure ace_passthrough
107typeset ace_secure_new
108
109# Defile the based directory and file
110basedir=$TESTDIR/basedir;  ofile=$TESTDIR/ofile; odir=$TESTDIR/odir
111
112test_requires ZFS_ACL
113
114# Define the files and directories will be created after chmod
115ndir1=$basedir/ndir1; ndir2=$ndir1/ndir2; ndir3=$ndir2/ndir3
116nfile1=$basedir/nfile1; nfile2=$ndir1/nfile2; nfile3=$ndir2/nfile3
117
118# Verify all the node have expected correct access control
119allnodes="$ndir1 $ndir2 $ndir3 $nfile1 $nfile2 $nfile3"
120
121typeset cifs=""
122if cifs_supported ; then
123	cifs="true"
124fi
125
126#
127# According to inherited flag, verify subdirectories and files within it has
128# correct inherited access control.
129#
130function verify_inherit #<aclinherit> <object> [strategy]
131{
132	# Define the nodes which will be affected by inherit.
133	typeset inherit_nodes
134	typeset inherit=$1
135	typeset obj=$2
136	typeset str=$3
137
138	# count: the ACE item to fetch
139	# pass: to mark if the current ACE should apply to the target
140	# maxnumber: predefine as 4
141	# passcnt: counter, if it achieves to maxnumber,
142	#	then no additional ACE should apply.
143	# isinherit: indicate if the current target is in the inherit list.
144	# step: indicate if the ACE be split during inherit.
145
146	typeset -i count=0 pass=0 passcnt=0 isinherit=0 maxnumber=4 step=0
147
148	log_must usr_exec $MKDIR -p $ndir3
149	log_must usr_exec $TOUCH $nfile1 $nfile2 $nfile3
150
151	# Get the files which inherited ACE.
152	if [[ $obj == *"file_inherit"* ]]; then
153		inherit_nodes="$inherit_nodes $nfile1"
154
155		if [[ $str != *"no_propagate"* ]]; then
156			inherit_nodes="$inherit_nodes $nfile2 $nfile3"
157		fi
158	fi
159	# Get the directores which inherited ACE.
160	if [[ $obj == *"dir_inherit"* ]]; then
161		inherit_nodes="$inherit_nodes $ndir1"
162
163		if [[ $str != *"no_propagate"* ]]; then
164			inherit_nodes="$inherit_nodes $ndir2 $ndir3"
165		fi
166	fi
167
168	for node in $allnodes; do
169		step=0
170		if [[ " $inherit_nodes " == *" $node "* ]]; then
171			isinherit=1
172			if [[ -d $node ]] ; then
173				step=1
174			fi
175		else
176			isinherit=0
177		fi
178
179		i=0
180		count=0
181		passcnt=0
182		while (( i < maxnumber )); do
183			pass=0
184			eval expect1=\$acl$i
185			expect2=$expect1
186
187		#
188		# aclinherit=passthrough,
189		# inherit all inheritable ACL entries without any
190		# modifications made to the ACL entries when they
191		# are inherited.
192		#
193		# aclinherit=secure,
194		# any inheritable ACL entries will remove
195		# write_acl and write_owner permissions when the ACL entry is
196		# inherited.
197		#
198		# aclinherit=noallow,
199		# only inherit inheritable ACE that specify "deny" permissions
200		#
201		# aclinherit=discard
202		# will not inherit any ACL entries
203		#
204
205			case $inherit in
206				passthrough)
207					;;
208				secure)
209					if [[ $expect1 == *":allow" ]] ; then
210						eval expect2=\$acls$i
211					fi
212					;;
213				noallow)
214					if [[ $expect1 == *":allow" ]] ; then
215						pass=1
216						(( passcnt = passcnt + 1 ))
217					fi
218					;;
219				discard)
220					passcnt=maxnumber
221					break
222					;;
223			esac
224
225			if (( pass == 0 )) ; then
226				acltemp=${expect2%:*}
227				acltemp=${acltemp%:*}
228				aclaction=${expect2##*:}
229
230				if [[ -n $cifs ]]; then
231					expect2=${acltemp}:inherited:${aclaction}
232				else
233					expect2=${acltemp}:${aclaction}
234				fi
235
236				acltemp=${expect1%:*}
237
238				if [[ -d $node ]]; then
239					if [[ $expect1 == *"no_propagate"* ]] ; then
240
241						#
242						# if no_propagate is set,
243						# then clear all inherit flags,
244						# only one ACE should left.
245						#
246
247						step=0
248						expect1=""
249
250					elif [[ $expect1 != *"inherit_only"* ]]; then
251
252						#
253						# directory should append
254						# "inherit_only" if not have
255						#
256
257						if [[ -n $cifs ]]; then
258
259							expect1=${acltemp}/inherit_only/inherited:${aclaction}
260						else
261							expect1=${acltemp}/inherit_only:${aclaction}
262						fi
263					elif [[ -n $cifs ]]; then
264						expect1=${acltemp}/inherited:${aclaction}
265					fi
266
267					#
268					# cleanup the first ACE if the directory
269					# not in inherit list
270					#
271
272					if (( isinherit == 0 )); then
273						expect1=""
274					fi
275				elif [[ -f $node ]] ; then
276					expect1=""
277				fi
278
279				# Get the first ACE to do comparison
280
281				aclcur=$(get_ACE $node $count)
282				aclcur=${aclcur#$count:}
283				if [[ -n $expect1 && $expect1 != $aclcur ]]; then
284					$LS -vd $basedir
285					$LS -vd $node
286					log_fail "$inherit $i #$count " \
287						"ACE: $aclcur, expect to be " \
288						"$expect1"
289				fi
290
291				# Get the second ACE (if should have) to do comparison
292
293				if (( step > 0 )); then
294					(( count = count + step ))
295
296					aclcur=$(get_ACE $node $count)
297					aclcur=${aclcur#$count:}
298					if [[ -n $expect2 && \
299						$expect2 != $aclcur ]]; then
300
301						$LS -vd $basedir
302						$LS -vd $node
303						log_fail "$inherit $i #$count " \
304							"ACE: $aclcur, expect to be " \
305							"$expect2"
306					fi
307				fi
308				(( count = count + 1 ))
309			fi
310			(( i = i + 1 ))
311		done
312
313		#
314		# If there's no any ACE be checked, it should be identify as
315		# an normal file/dir, verify it.
316		#
317
318		if (( passcnt == maxnumber )); then
319			if [[ -d $node ]]; then
320				compare_acls $node $odir
321			elif [[	-f $node ]]; then
322				compare_acls $node $ofile
323			fi
324
325			if [[ $? -ne 0 ]]; then
326				$LS -vd $basedir
327				$LS -vd $node
328				log_fail "Unexpect acl: $node, $inherit ($str)"
329			fi
330		fi
331	done
332}
333
334typeset -i i=0
335typeset acl0 acl1 acl2 acl3
336typeset acls0 acls1 acls2 acls3
337
338#
339# Set aclmode=passthrough to make sure
340# the acl will not change during chmod.
341# A general testing should verify the combination of
342# aclmode/aclinherit works well,
343# here we just simple test them separately.
344#
345
346log_must $ZFS set aclmode=passthrough $TESTPOOL/$TESTFS
347
348for inherit in "${aclinherit_flag[@]}"; do
349
350	#
351	# Set different value of aclinherit
352	#
353
354	log_must $ZFS set aclinherit=$inherit $TESTPOOL/$TESTFS
355
356	for user in root $ZFS_ACL_STAFF1; do
357		log_must set_cur_usr $user
358
359		for obj in "${object_flag[@]}"; do
360			for str in "${strategy_flag[@]}"; do
361				typeset inh_opt=$obj
362				(( ${#str} != 0 )) && inh_opt=$inh_opt/$str
363
364				#
365				# Prepare 4 ACES, which should include :
366				# deny -> to verify "noallow"
367				# write_acl/write_owner -> to verify "secure"
368				#
369
370				acl0="$ace_prefix1:read_xattr/write_acl/write_owner:$inh_opt:deny"
371				acl1="$ace_prefix2:read_xattr/write_acl/write_owner:$inh_opt:allow"
372				acl2="$ace_prefix1:read_xattr:$inh_opt:deny"
373				acl3="$ace_prefix2:read_xattr:$inh_opt:allow"
374
375				#
376				# The ACE filtered by write_acl/write_owner
377				#
378
379				acls0="$ace_prefix1:read_xattr:$inh_opt:deny"
380				acls1="$ace_prefix2:read_xattr:$inh_opt:allow"
381				acls2=$acl2
382				acls3=$acl3
383
384
385				#
386				# Create basedir and tmp dir/file
387				# for comparison.
388				#
389
390				log_note "$user: $CHMOD $acl $basedir"
391				log_must usr_exec $MKDIR $basedir
392				log_must usr_exec $MKDIR $odir
393				log_must usr_exec $TOUCH $ofile
394
395				i=3
396				while (( i >= 0 )); do
397					eval acl=\$acl$i
398
399				#
400				# Place on a directory should succeed.
401				#
402					log_must usr_exec $CHMOD A+$acl $basedir
403
404					(( i = i - 1 ))
405				done
406
407				verify_inherit $inherit $obj $str
408
409				log_must usr_exec $RM -rf $ofile $odir $basedir
410			done
411		done
412	done
413done
414
415log_pass "Verify chmod inherit behaviour co-op with aclinherit setting passed."
416