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_003_pos.ksh	1.1	08/08/15 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_003_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 (2008-07-04)
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 "f-" "-d" "fd"
100set -A strategy_flag "--" "i-" "-n" "in"
101
102typeset ace_prefix1="owner@"
103typeset ace_prefix2="group@"
104typeset ace_prefix3="everyone@"
105typeset ace_discard ace_noallow ace_secure ace_passthrough
106typeset ace_secure_new
107
108# Defile the based directory and file
109basedir=$TESTDIR/basedir;  ofile=$TESTDIR/ofile; odir=$TESTDIR/odir
110
111test_requires ZFS_ACL
112
113# Define the files and directories will be created after chmod
114ndir1=$basedir/ndir1; ndir2=$ndir1/ndir2; ndir3=$ndir2/ndir3
115nfile1=$basedir/nfile1; nfile2=$ndir1/nfile2; nfile3=$ndir2/nfile3
116
117# Verify all the node have expected correct access control
118allnodes="$ndir1 $ndir2 $ndir3 $nfile1 $nfile2 $nfile3"
119
120typeset cifs=""
121if cifs_supported ; then
122	cifs="true"
123fi
124
125#
126# According to inherited flag, verify subdirectories and files within it has
127# correct inherited access control.
128#
129function verify_inherit #<aclinherit> <object> [strategy]
130{
131	# Define the nodes which will be affected by inherit.
132	typeset inherit_nodes
133	typeset inherit=$1
134	typeset obj=$2
135	typeset str=$3
136
137	# count: the ACE item to fetch
138	# pass: to mark if the current ACE should apply to the target
139	# maxnumber: predefine as 4
140	# passcnt: counter, if it achieves to maxnumber,
141	#	then no additional ACE should apply.
142	# isinherit: indicate if the current target is in the inherit list.
143	# step: indicate if the ACE be split during inherit.
144
145	typeset -i count=0 pass=0 passcnt=0 isinherit=0 maxnumber=4 step=0
146
147	log_must usr_exec $MKDIR -p $ndir3
148	log_must usr_exec $TOUCH $nfile1 $nfile2 $nfile3
149
150	# Get the files which inherited ACE.
151	if [[ $(get_substr $obj 1 1) == f ]]; then
152		inherit_nodes="$inherit_nodes $nfile1"
153
154		if [[ $(get_substr $str 2 1) != n ]]; then
155			inherit_nodes="$inherit_nodes $nfile2 $nfile3"
156		fi
157	fi
158	# Get the directores which inherited ACE.
159	if [[ $(get_substr $obj 2 1) == d ]]; then
160		inherit_nodes="$inherit_nodes $ndir1"
161
162		if [[ $(get_substr $str 2 1) != n ]]; then
163			inherit_nodes="$inherit_nodes $ndir2 $ndir3"
164		fi
165	fi
166
167	for node in $allnodes; do
168		step=0
169		if [[ " $inherit_nodes " == *" $node "* ]]; then
170			isinherit=1
171			if [[ -d $node ]] ; then
172				step=1
173			fi
174		else
175			isinherit=0
176		fi
177
178		i=0
179		count=0
180		passcnt=0
181		while (( i < maxnumber )); do
182			pass=0
183			eval expect1=\$acl$i
184			expect2=$expect1
185
186		#
187		# aclinherit=passthrough,
188		# inherit all inheritable ACL entries without any
189		# modifications made to the ACL entries when they
190		# are inherited.
191		#
192		# aclinherit=secure,
193		# any inheritable ACL entries will remove
194		# write_acl and write_owner permissions when the ACL entry is
195		# inherited.
196		#
197		# aclinherit=noallow,
198		# only inherit inheritable ACE that specify "deny" permissions
199		#
200		# aclinherit=discard
201		# will not inherit any ACL entries
202		#
203
204			case $inherit in
205				passthrough)
206					if [[ -z $cifs ]]; then
207						break
208					fi
209
210					action=${expect1##*:}
211					expect1=${expect1%:$action}
212					expect1=${expect1%-}
213					expect1=${expect1%I}
214					expect1=${expect1}I:$action
215					;;
216				secure)
217					eval expect2=\$acls$i
218					;;
219				noallow)
220					if [[ $expect1 == *":allow" ]] ; then
221						pass=1
222						(( passcnt = passcnt + 1 ))
223					else
224						eval expect2=\$acls$i
225					fi
226					;;
227				discard)
228					passcnt=maxnumber
229					break
230					;;
231			esac
232
233			if (( pass == 0 )) ; then
234				acltemp=${expect2%:*}
235				acltemp=${acltemp%:*}
236				aclaction=${expect2##*:}
237
238				if [[ -n $cifs ]]; then
239					expect2=${acltemp}:------I:${aclaction}
240				else
241					expect2=${acltemp}:------:${aclaction}
242				fi
243
244				acltemp=${expect1%:*}
245				inh=${acltemp##*:}
246
247				if [[ -d $node ]]; then
248					if [[ $(get_substr $inh 4 1) == n ]]; then
249
250						#
251						# if no_propagate is set,
252						# then clear all inherit flags,
253						# only one ACE should left.
254						#
255
256						step=0
257						expect1=""
258
259					elif [[ $(get_substr $inh 3 1) != i ]]; then
260
261						#
262						# directory should append
263						# "inherit_only" if not have
264						#
265						acltemp=${acltemp%i*}
266						if [[ -n $cifs ]]; then
267
268							expect1=${acltemp}i---I:${aclaction}
269						else
270							expect1=${acltemp}i---:${aclaction}
271						fi
272					elif [[ -n $cifs ]]; then
273						acltemp=${acltemp%-}
274						acltemp=${acltemp%I}
275						expect1=${acltemp}I:${aclaction}
276					fi
277
278					#
279					# cleanup the first ACE if the directory
280					# not in inherit list
281					#
282
283					if (( isinherit == 0 )); then
284						expect1=""
285					fi
286				elif [[ -f $node ]] ; then
287					expect1=""
288				fi
289
290				# Get the first ACE to do comparison
291
292				aclcur=$(get_ACE $node $count compact)
293				aclcur=${aclcur#$count:}
294				if [[ -n $expect1 && $expect1 != $aclcur ]]; then
295					$LS -Vd $basedir
296					$LS -Vd $node
297					log_fail "$inherit $i #$count " \
298						"ACE: $aclcur, expect to be " \
299						"$expect1"
300				fi
301
302				# Get the second ACE (if should have) to do comparison
303
304				if (( step > 0 )); then
305					(( count = count + step ))
306
307					aclcur=$(get_ACE $node $count compact)
308					aclcur=${aclcur#$count:}
309					if [[ -n $expect2 && \
310						$expect2 != $aclcur ]]; then
311
312						$LS -Vd $basedir
313						$LS -Vd $node
314						log_fail "$inherit $i #$count " \
315							"ACE: $aclcur, expect to be " \
316							"$expect2"
317					fi
318				fi
319				(( count = count + 1 ))
320			fi
321			(( i = i + 1 ))
322		done
323
324		#
325		# If there's no any ACE be checked, it should be identify as
326		# an normal file/dir, verify it.
327		#
328
329		if (( passcnt == maxnumber )); then
330			if [[ -d $node ]]; then
331				compare_acls $node $odir
332			elif [[	-f $node ]]; then
333				compare_acls $node $ofile
334			fi
335
336			if [[ $? -ne 0 ]]; then
337				$LS -Vd $basedir
338				$LS -Vd $node
339				log_fail "Unexpect acl: $node, $inherit ($str)"
340			fi
341		fi
342	done
343}
344
345typeset -i i=0
346typeset acl0 acl1 acl2 acl3
347typeset acls0 acls1 acls2 acls3
348
349#
350# Set aclmode=passthrough to make sure
351# the acl will not change during chmod.
352# A general testing should verify the combination of
353# aclmode/aclinherit works well,
354# here we just simple test them separately.
355#
356
357log_must $ZFS set aclmode=passthrough $TESTPOOL/$TESTFS
358
359for inherit in "${aclinherit_flag[@]}"; do
360
361	#
362	# Set different value of aclinherit
363	#
364
365	log_must $ZFS set aclinherit=$inherit $TESTPOOL/$TESTFS
366
367	for user in root $ZFS_ACL_STAFF1; do
368		log_must set_cur_usr $user
369
370		for obj in "${object_flag[@]}"; do
371			for str in "${strategy_flag[@]}"; do
372				typeset inh_opt=$obj
373				(( ${#str} != 0 )) && inh_opt=${inh_opt}${str}--
374
375				if [[ -n $cifs ]]; then
376					inh_a=${inh_opt}-
377					inh_b=${inh_opt}I
378				else
379					inh_a=${inh_opt}
380					inh_b=${inh_opt}
381				fi
382
383				#
384				# Prepare 4 ACES, which should include :
385				# deny -> to verify "noallow"
386				# write_acl/write_owner -> to verify "secure"
387				#
388
389				acl0="$ace_prefix1:rwxp---A-W-Co-:${inh_a}:allow"
390				acl1="$ace_prefix2:rwxp---A-W-Co-:${inh_a}:deny"
391				acl2="$ace_prefix3:rwxp---A-W-Co-:${inh_a}:allow"
392				acl3="$ace_prefix1:-------A-W----:${inh_a}:deny"
393				acl4="$ace_prefix2:-------A-W----:${inh_a}:allow"
394				acl5="$ace_prefix3:-------A-W----:${inh_a}:deny"
395
396
397				#
398				# The ACE filtered by write_acl/write_owner
399				#
400
401				if [[ $inheri == "passthrough" ]]; then
402					acls0="$ace_prefix1:rwxp---A-W----:${inh_b}:allow"
403					acls1="$ace_prefix2:rwxp---A-W----:${inh_b}:deny"
404					acls2="$ace_prefix3:rwxp---A-W----:${inh_b}:allow"
405					acls3="$ace_prefix1:rwxp---A-W----:${inh_b}:deny"
406					acls4="$ace_prefix2:rwxp---A-W----:${inh_b}:allow"
407					acls5="$ace_prefix3:rwxp---A-W----:${inh_b}:deny"
408				else
409					acls0="$ace_prefix1:-------A-W----:${inh_b}:allow"
410					acls1="$ace_prefix2:-------A-W-Co-:${inh_b}:deny"
411					acls2="$ace_prefix3:-------A-W----:${inh_b}:allow"
412					acls3="$ace_prefix1:-------A-W----:${inh_b}:deny"
413					acls4="$ace_prefix2:-------A-W----:${inh_b}:allow"
414					acls5="$ace_prefix3:-------A-W----:${inh_b}:deny"
415				fi
416
417				#
418				# Create basedir and tmp dir/file
419				# for comparison.
420				#
421
422				log_note "$user: $CHMOD $acl $basedir"
423				log_must usr_exec $MKDIR $basedir
424				log_must usr_exec $MKDIR $odir
425				log_must usr_exec $TOUCH $ofile
426
427				i=5
428				while (( i >= 0 )); do
429					eval acl=\$acl$i
430
431				#
432				# Place on a directory should succeed.
433				#
434					log_must usr_exec $CHMOD A+$acl $basedir
435
436					(( i = i - 1 ))
437				done
438
439				verify_inherit $inherit $obj $str
440
441				log_must usr_exec $RM -rf $ofile $odir $basedir
442			done
443		done
444	done
445done
446
447log_pass "Verify chmod inherit behaviour co-op with aclinherit setting passed."
448