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