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