1#!/bin/ksh -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 2009 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27
28#
29# Copyright (c) 2016 by Delphix. All rights reserved.
30# Copyright 2023 RackTop Systems, Inc.
31#
32
33. $STF_SUITE/tests/functional/acl/acl_common.kshlib
34
35#
36# DESCRIPTION:
37#	Verify assigned read_acl/write_acl to owner@/group@/everyone@,
38#	specificied user and group. File have the correct access permission.
39#
40# STRATEGY:
41#	1. Separatedly verify file and directory was assigned read_acl/write_acl
42#	   by root and non-root user.
43#	2. Verify owner can read and write acl.
44#	3. Verify group access permission, when group was assigned
45#	   read_acl/write_acl.
46#	4. Verify access permission, after everyone was assigned read_acl/write.
47#	5. Verify everyone@ was deny except specificied user, this user can read
48#	   and write acl.
49#	6. Verify the group was deny except specified user, this user can read
50#	   and write acl
51#
52
53verify_runnable "both"
54
55log_assert "Verify chmod A[number]{+|-|=} read_acl/write_acl have correct " \
56	"behaviour to access permission."
57log_onexit cleanup
58
59function read_ACL #<node> <user1> <user2> ...
60{
61	typeset node=$1
62	typeset user
63	typeset -i ret
64
65	shift
66	for user in $@; do
67		chgusr_exec $user ls -vd $node > /dev/null 2>&1
68		ret=$?
69		(( ret != 0 )) && return $ret
70
71		shift
72	done
73
74	return 0
75}
76
77function write_ACL #<node> <user1> <user2> ...
78{
79	typeset node=$1
80	typeset user
81	typeset -i ret before_cnt after_cnt
82
83	shift
84	for user in "$@"; do
85		before_cnt=$(count_ACE $node)
86		ret=$?;
87		(( ret != 0 )) && return $ret
88
89		chgusr_exec $user chmod A0+owner@:read_data:allow $node
90		ret=$?
91		(( ret != 0 )) && return $ret
92
93		after_cnt=$(count_ACE $node)
94		ret=$?
95		(( ret != 0 )) && return $ret
96
97		chgusr_exec $user chmod A0- $node
98		ret=$?
99		(( ret != 0 )) && return $ret
100
101		if (( after_cnt - before_cnt != 1 )); then
102			return 1
103		fi
104
105		shift
106	done
107
108	return 0
109}
110
111function check_owner #<node>
112{
113	typeset node=$1
114	typeset log
115
116	for acc in allow deny; do
117		if [[ $aclimplicit == on ||
118		    $acc == allow || $ZFS_ACL_CUR_USER == root ]]; then
119			log=log_must
120		else
121			log=log_mustnot
122		fi
123		log_must usr_exec \
124			chmod A0+owner@:read_acl/write_acl:$acc $node
125		# at this time we can always read acl
126		log_must read_ACL $node $ZFS_ACL_CUR_USER
127		$log write_ACL $node $ZFS_ACL_CUR_USER
128		# only root can remove write_acl:deny
129		log_must chgusr_exec root chmod A0- $node
130	done
131}
132
133function check_group #<node>
134{
135	typeset node=$1
136
137	typeset grp_usr=""
138	if [[ $ZFS_ACL_CUR_USER == root ]]; then
139		grp_usr=$ZFS_ACL_ADMIN
140	elif [[ $ZFS_ACL_CUR_USER == $ZFS_ACL_STAFF1 ]]; then
141		grp_usr=$ZFS_ACL_STAFF2
142	fi
143
144	log_must usr_exec chmod A0+group@:read_acl/write_acl:allow $node
145	log_must read_ACL $node $grp_usr
146	log_must write_ACL $node $grp_usr
147	log_must usr_exec chmod A0- $node
148
149	log_must usr_exec chmod A0+group@:read_acl/write_acl:deny $node
150	log_mustnot read_ACL $node $grp_usr
151	log_mustnot write_ACL $node $grp_usr
152	# only root can remove write_acl:deny
153	log_must chgusr_exec root chmod A0- $node
154}
155
156function check_everyone #<node>
157{
158	typeset node=$1
159	typeset log
160
161	typeset flag
162	for flag in allow deny; do
163		if [[ $flag == allow ]]; then
164			log=log_must
165		else
166			log=log_mustnot
167		fi
168
169		log_must usr_exec \
170			chmod A0+everyone@:read_acl/write_acl:$flag $node
171
172		$log read_ACL $node $ZFS_ACL_OTHER1 $ZFS_ACL_OTHER2
173		$log write_ACL $node $ZFS_ACL_OTHER1 $ZFS_ACL_OTHER2
174
175		# only root can remove write_acl:deny
176		log_must chgusr_exec root chmod A0- $node
177	done
178}
179
180function check_spec_user #<node>
181{
182	typeset node=$1
183
184	log_must usr_exec chmod A0+everyone@:read_acl/write_acl:deny $node
185	log_must chgusr_exec root \
186		chmod A0+user:$ZFS_ACL_OTHER1:read_acl/write_acl:allow $node
187
188	# The specified user can read and write acl
189	log_must read_ACL $node $ZFS_ACL_OTHER1
190	log_must write_ACL $node $ZFS_ACL_OTHER1
191
192	# All the other user can't read and write acl
193	log_mustnot \
194		read_ACL $node $ZFS_ACL_ADMIN $ZFS_ACL_STAFF2 $ZFS_ACL_OTHER2
195	log_mustnot \
196		write_ACL $node $ZFS_ACL_ADMIN $ZFS_ACL_STAFF2 $ZFS_ACL_OTHER2
197
198	# only root can remove write_acl:deny
199	log_must chgusr_exec root chmod A0- $node
200	log_must chgusr_exec root chmod A0- $node
201}
202
203function check_spec_group #<node>
204{
205	typeset node=$1
206
207	log_must usr_exec chmod A0+everyone@:read_acl/write_acl:deny $node
208	log_must chgusr_exec root chmod \
209		A0+group:$ZFS_ACL_OTHER_GROUP:read_acl/write_acl:allow $node
210
211	# The specified group can read and write acl
212	log_must read_ACL $node $ZFS_ACL_OTHER1 $ZFS_ACL_OTHER2
213	log_must write_ACL $node $ZFS_ACL_OTHER1 $ZFS_ACL_OTHER2
214
215	# All the other user can't read and write acl
216	log_mustnot read_ACL $node $ZFS_ACL_ADMIN $ZFS_ACL_STAFF2
217	log_mustnot write_ACL $node $ZFS_ACL_ADMIN $ZFS_ACL_STAFF2
218
219	# only root can remove write_acl:deny
220	log_must chgusr_exec root chmod A0- $node
221	log_must chgusr_exec root chmod A0- $node
222}
223
224function check_user_in_group #<node>
225{
226	typeset node=$1
227
228	log_must usr_exec chmod \
229		A0+group:$ZFS_ACL_OTHER_GROUP:read_acl/write_acl:deny $node
230	log_must usr_exec chmod \
231		A0+user:$ZFS_ACL_OTHER1:read_acl/write_acl:allow $node
232	log_must read_ACL $node $ZFS_ACL_OTHER1
233	log_must write_ACL $node $ZFS_ACL_OTHER1
234	log_mustnot read_ACL $node $ZFS_ACL_OTHER2
235	log_mustnot write_ACL $node $ZFS_ACL_OTHER2
236
237	log_must usr_exec chmod A0- $node
238	log_must usr_exec chmod A0- $node
239}
240
241set -A func_name check_owner \
242		check_group \
243		check_everyone \
244		check_spec_user \
245		check_spec_group \
246		check_user_in_group
247
248typeset a_prop="on off"
249typeset aclimplicit=$(zfs get -Ho value aclimplicit $TESTPOOL/$TESTFS)
250typeset val
251
252for val in $a_prop; do
253	log_must zfs set aclimplicit=$val $TESTPOOL/$TESTFS
254	aclimplicit=$(zfs get -Ho value aclimplicit $TESTPOOL/$TESTFS)
255	if [[ $val == off ]]; then
256		# aclimplicit=off also needs aclmode=passthrough and
257		# aclinherit=passthrough
258		log_must zfs set aclmode=passthrough $TESTPOOL/$TESTFS
259		log_must zfs set aclinherit=passthrough $TESTPOOL/$TESTFS
260	fi
261
262	for user in root $ZFS_ACL_STAFF1; do
263		log_must set_cur_usr $user
264
265		log_must usr_exec touch $testfile
266		log_must usr_exec mkdir $testdir
267
268		typeset func node
269		for func in ${func_name[@]}; do
270			for node in $testfile $testdir; do
271				eval $func \$node
272			done
273		done
274
275		log_must usr_exec rm -rf $testfile $testdir
276	done
277done
278
279# restore defaults
280log_must zfs inherit aclmode $TESTPOOL/$TESTFS
281log_must zfs inherit aclinherit $TESTPOOL/$TESTFS
282log_must zfs inherit aclimplicit $TESTPOOL/$TESTFS
283
284log_pass "Verify chmod A[number]{+|-|=} read_acl/write_acl passed."
285