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 2008 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27
28#
29# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
30#
31
32. $STF_SUITE/tests/functional/acl/acl_common.kshlib
33. $STF_SUITE/tests/functional/acl/cifs/cifs.kshlib
34
35#
36# DESCRIPTION:
37#	Verify the user with write_attributes permission or
38#	PRIV_FILE_OWNER privilege could set/clear DOS attributes.
39#	(Readonly, Hidden, Archive, System)
40#
41# STRATEGY:
42#	1. Loop super user and non-super user to run the test case.
43#	2. Create basedir and a set of subdirectores and files within it.
44#	3. Grant user has write_attributes permission or
45#		PRIV_FILE_OWNER privilege
46#	4. Verify set/clear DOS attributes should succeed.
47#
48
49verify_runnable "both"
50
51function cleanup
52{
53	for fs in $TESTPOOL/$TESTFS $TESTPOOL ; do
54		mtpt=$(get_prop mountpoint $fs)
55		log_must rm -rf $mtpt/file.* $mtpt/dir.*
56	done
57}
58
59#
60# Set the special attribute to the given node
61#
62# $1: The given node (file/dir)
63# $2: The special attribute to be set
64# $3: Execute username
65#
66function set_attribute
67{
68	typeset object=$1
69	typeset attr=${2:-AHRS}
70	typeset user=$3
71	typeset ret=0
72
73	if [[ -z $object ]]; then
74		log_fail "Object not defined."
75	fi
76
77	if [[ -n $user ]]; then
78		su $user -c "chmod S+c${attr} $object"
79		ret=$?
80	else
81		chmod S+c${attr} $object
82		ret=$?
83	fi
84
85	return $ret
86}
87
88#
89# Clear the special attribute to the given node
90#
91# $1: The given node (file/dir)
92# $2: The special attribute to be cleared
93# $3: Execute username
94#
95function clear_attribute
96{
97	typeset object=$1
98	typeset attr=${2:-AHRS}
99	typeset user=$3
100	typeset ret=0
101
102	if [[ -z $object ]]; then
103		log_fail "Object not defined."
104	fi
105
106	if [[ -n $user ]]; then
107		su $user -c "chmod S-c${attr} $object"
108		ret=$?
109	else
110		chmod S-c${attr} $object
111		ret=$?
112	fi
113
114	return $ret
115}
116
117#
118# Grant the ace of write_attributes to the given user
119#
120# $1: The given user
121# $2: The given node (file/dir)
122#
123function grant_attr
124{
125	typeset user=$1
126	typeset object=$2
127
128	if [[ -z $user || -z $object ]]; then
129		log_fail "User($user), Object($object) not defined."
130	fi
131
132	# To increase the coverage, here we set 'deny' against
133	# superuser and owner.
134	# Only grant the user explicitly while it's not root neither owner.
135
136	if [[ $user == "root" ]]; then
137		log_must chmod A+user:root:write_attributes:deny $object
138	elif [[ $user == $(get_owner $object) ]]; then
139		if (((RANDOM % 2) == 0)); then
140			log_must chmod A+owner@:write_attributes:deny $object
141		else
142			log_must chmod A+user:$user:write_attributes:deny \
143			    $object
144		fi
145	else
146		log_must chmod A+user:$user:write_attributes:allow $object
147	fi
148	attr_mod="write_attributes"
149}
150
151#
152# Revoke the ace of write_attributes from the given user
153#
154# $1: The given user
155# $2: The given node (file/dir)
156#
157function revoke_attr
158{
159	typeset user=$1
160	typeset object=$2
161
162	if [[ -z $user || -z $object ]]; then
163		log_fail "User($user), Object($object) not defined."
164	fi
165
166	log_must chmod A0- $object
167	attr_mod=
168}
169
170#
171# Invoke the function and verify whether its return code as expected
172#
173# $1: Function be invoked
174# $2: The given node (file/dir)
175# $3: Execute user
176# $4: Option
177#
178function verify_attr
179{
180	typeset func=$1
181	typeset object=$2
182	typeset opt=$3
183	typeset user=$4
184	typeset expect="log_mustnot"
185
186	if [[ -z $func || -z $object ]]; then
187		log_fail "Func($func), Object($object), User($user), \
188		    Opt($opt) not defined."
189	fi
190
191	# If user is superuser or has write_attributes permission or
192	# PRIV_FILE_OWNER privilege, it should log_must,
193	# otherwise log_mustnot.
194
195	if [[ -z $user ||  $user == "root"  || $user == \
196	    $(get_owner $object) || $attr_mod == *"write_attributes"* ]] ; then
197		expect="log_must"
198	fi
199
200	$expect $func $object $opt $user
201}
202
203log_assert "Verify set/clear DOS attributes will succeed while user has " \
204    "write_attributes permission or PRIV_FILE_OWNER privilege"
205log_onexit cleanup
206
207file="file.0"
208dir="dir.0"
209XATTROPTIONS="H S R A"
210
211for fs in $TESTPOOL $TESTPOOL/$TESTFS ; do
212	mtpt=$(get_prop mountpoint $fs)
213	for owner in root $ZFS_ACL_STAFF1 ; do
214
215		create_object "file" $mtpt/$file $owner
216		create_object "dir" $mtpt/$dir $owner
217
218		for object in $mtpt/$file $mtpt/$dir ; do
219			for user in root $ZFS_ACL_STAFF2 ; do
220				for opt in $XATTROPTIONS ; do
221					verify_attr set_attribute \
222					    $object $opt $user
223					verify_attr clear_attribute \
224					    $object $opt $user
225				done
226				log_must grant_attr $user $object
227				for opt in $XATTROPTIONS ; do
228					verify_attr set_attribute \
229					    $object $opt $user
230					verify_attr clear_attribute \
231					    $object $opt $user
232				done
233				log_must revoke_attr $user $object
234			done
235		done
236		destroy_object $mtpt/$file $mtpt/$dir
237	done
238done
239
240log_pass "Set/Clear DOS attributes succeed while user has " \
241    "write_attributes permission or PRIV_FILE_OWNER privilege"
242