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