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 2009 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26 27. $STF_SUITE/tests/acl/acl_common.kshlib 28. $STF_SUITE/tests/acl/cifs/cifs.kshlib 29 30################################################################################# 31# 32# __stc_assertion_start 33# 34# ID: cifs_attr_003_pos 35# 36# DESCRIPTION: 37# Verify the DOS attributes (Readonly, Hidden, Archive, System) 38# and BSD'ish attributes (Immutable, nounlink, and appendonly) 39# will provide the proper access limitation as expected. 40# 41# Readonly means that the content of a file can't be modified, but 42# timestamps, mode and so on can. 43# 44# Archive - Indicates if a file should be included in the next backup 45# of the file system. ZFS will set this bit whenever a file is 46# modified. 47# 48# Hidden and System (ZFS does nothing special with these, other than 49# letting a user/application set them. 50# 51# Immutable (The data can't, change nor can mode, ACL, size and so on) 52# The only attribute that can be updated is the access time. 53# 54# Nonunlink - Sort of like immutable except that a file/dir can't be 55# removed. 56# This will also effect a rename operation, since that involes a 57# remove. 58# 59# Appendonly - File can only be appended to. 60# 61# nodump, settable, opaque (These are for the MacOS port) we will 62# allow them to be set, but have no semantics tied to them. 63# 64# STRATEGY: 65# 1. Loop super user and non-super user to run the test case. 66# 2. Create basedir and a set of subdirectores and files within it. 67# 3. Set the file/dir with each kind of special attribute. 68# 4. Verify the access limitation works as expected. 69# 70# TESTABILITY: explicit 71# 72# TEST_AUTOMATION_LEVEL: automated 73# 74# CODING_STATUS: COMPLETED (2007-11-05) 75# 76# __stc_assertion_end 77# 78################################################################################ 79 80verify_runnable "both" 81 82if ! cifs_supported ; then 83 log_unsupported "CIFS not supported on current system." 84fi 85 86test_requires ZFS_ACL ZFS_XATTR 87 88function cleanup 89{ 90 if [[ -n $gobject ]]; then 91 destroy_object $gobject 92 fi 93 94 for fs in $TESTPOOL/$TESTFS $TESTPOOL ; do 95 mtpt=$(get_prop mountpoint $fs) 96 log_must $RM -rf $mtpt/file.* $mtpt/dir.* 97 done 98} 99 100# 101# Set the special attribute to the given node 102# 103# $1: The given node (file/dir) 104# $2: The special attribute to be set 105# 106function set_attribute 107{ 108 typeset object=$1 109 typeset attr=$2 110 111 if [[ -z $attr ]]; then 112 attr="AHRSadimu" 113 if [[ -f $object ]]; then 114 attr="${attr}q" 115 fi 116 fi 117 118 $CHMOD S+c${attr} $object 119 return $? 120} 121 122# 123# Clear the special attribute to the given node 124# 125# $1: The given node (file/dir) 126# $2: The special attribute to be cleared 127# 128function clear_attribute 129{ 130 typeset object=$1 131 typeset attr=$2 132 133 if [[ -z $attr ]]; then 134 if is_global_zone ; then 135 attr="AHRSadimu" 136 if [[ -f $object ]]; then 137 attr="${attr}q" 138 fi 139 else 140 attr="AHRS" 141 fi 142 fi 143 144 $CHMOD S-c${attr} $object 145 return $? 146} 147 148# 149# A wrapper function to call test function according to the given attr 150# 151# $1: The given node (file/dir) 152# $2: The special attribute to be test 153# 154function test_wrapper 155{ 156 typeset object=$1 157 typeset attr=$2 158 159 if [[ -z $object || -z $attr ]]; then 160 log_fail "Object($object), Attr($attr) not defined." 161 fi 162 163 case $attr in 164 R) func=test_readonly 165 ;; 166 i) func=test_immutable 167 ;; 168 u) func=test_nounlink 169 ;; 170 a) func=test_appendonly 171 ;; 172 esac 173 174 if [[ -n $func ]]; then 175 $func $object 176 fi 177} 178 179# 180# Invoke the function and verify whether its return code as expected 181# 182# $1: Expect value 183# $2-$n: Function and args need to be invoked 184# 185function verify_expect 186{ 187 typeset -i expect=$1 188 typeset status 189 190 shift 191 192 "$@" > /dev/null 2>&1 193 status=$? 194 if [[ $status -eq 0 ]]; then 195 if (( expect != 0 )); then 196 log_fail "$@ unexpect return 0" 197 fi 198 else 199 if (( expect == 0 )); then 200 log_fail "$@ unexpect return $status" 201 fi 202 fi 203} 204 205# 206# Unit testing function against overwrite file 207# 208# $1: The given file node 209# $2: Execute user 210# $3: Expect value, default to be zero 211# 212function unit_writefile 213{ 214 typeset object=$1 215 typeset user=$2 216 typeset expect=${3:-0} 217 218 if [[ -f $object ]]; then 219 verify_expect $expect $CHG_USR_EXEC $user \ 220 $CP $TESTFILE $object 221 verify_expect $expect $CHG_USR_EXEC $user \ 222 $EVAL "$ECHO '$TESTSTR' > $object" 223 fi 224} 225 226# 227# Unit testing function against write new stuffs into a directory 228# 229# $1: The given directory node 230# $2: Execute user 231# $3: Expect value, default to be zero 232# 233function unit_writedir 234{ 235 typeset object=$1 236 typeset user=$2 237 typeset expect=${3:-0} 238 239 if [[ -d $object ]]; then 240 verify_expect $expect $CHG_USR_EXEC $user \ 241 $CP $TESTFILE $object 242 verify_expect $expect $CHG_USR_EXEC $user \ 243 $MKDIR -p $object/$TESTDIR 244 fi 245} 246 247function unit_appenddata 248{ 249 typeset object=$1 250 typeset user=$2 251 typeset expect=${3:-0} 252 253 if [[ ! -d $object ]]; then 254 verify_expect $expect $CHG_USR_EXEC $user \ 255 $EVAL "$ECHO '$TESTSTR' >> $object" 256 fi 257} 258 259# 260# Unit testing function against delete content from a directory 261# 262# $1: The given node, dir 263# $2: Execute user 264# $3: Expect value, default to be zero 265# 266function unit_deletecontent 267{ 268 typeset object=$1 269 typeset user=$2 270 typeset expect=${3:-0} 271 272 if [[ -d $object ]]; then 273 for target in $object/${TESTFILE##*/} $object/$TESTDIR ; do 274 if [[ -e $target ]]; then 275 verify_expect $expect $CHG_USR_EXEC $user \ 276 $EVAL "$MV $target $target.new" 277 verify_expect $expect $CHG_USR_EXEC $user \ 278 $EVAL "$ECHO y | $RM -r $target.new" 279 fi 280 done 281 fi 282} 283 284# 285# Unit testing function against delete a node 286# 287# $1: The given node, file/dir 288# $2: Execute user 289# $3: Expect value, default to be zero 290# 291function unit_deletedata 292{ 293 typeset object=$1 294 typeset user=$2 295 typeset expect=${3:-0} 296 297 verify_expect $expect $CHG_USR_EXEC $user \ 298 $EVAL "$ECHO y | $RM -r $object" 299 300} 301 302# 303# Unit testing function against write xattr to a node 304# 305# $1: The given node, file/dir 306# $2: Execute user 307# $3: Expect value, default to be zero 308# 309function unit_writexattr 310{ 311 typeset object=$1 312 typeset user=$2 313 typeset expect=${3:-0} 314 315 verify_expect $expect $CHG_USR_EXEC $user \ 316 $RUNAT $object "$CP $TESTFILE $TESTATTR" 317 verify_expect $expect $CHG_USR_EXEC $user \ 318 $EVAL "$RUNAT $object \"$ECHO '$TESTSTR' > $TESTATTR\"" 319 verify_expect $expect $CHG_USR_EXEC $user \ 320 $EVAL "$RUNAT $object \"$ECHO '$TESTSTR' >> $TESTATTR\"" 321 if [[ $expect -eq 0 ]]; then 322 verify_expect $expect $CHG_USR_EXEC $user \ 323 $RUNAT $object "$RM -f $TESTATTR" 324 fi 325} 326 327# 328# Unit testing function against modify accesstime of a node 329# 330# $1: The given node, file/dir 331# $2: Execute user 332# $3: Expect value, default to be zero 333# 334function unit_accesstime 335{ 336 typeset object=$1 337 typeset user=$2 338 typeset expect=${3:-0} 339 340 if [[ -d $object ]]; then 341 verify_expect $expect $CHG_USR_EXEC $user $LS $object 342 else 343 verify_expect $expect $CHG_USR_EXEC $user $CAT $object 344 fi 345} 346 347# 348# Unit testing function against modify updatetime of a node 349# 350# $1: The given node, file/dir 351# $2: Execute user 352# $3: Expect value, default to be zero 353# 354function unit_updatetime 355{ 356 typeset object=$1 357 typeset user=$2 358 typeset expect=${3:-0} 359 360 verify_expect $expect $CHG_USR_EXEC $user $TOUCH $object 361 verify_expect $expect $CHG_USR_EXEC $user $TOUCH -a $object 362 verify_expect $expect $CHG_USR_EXEC $user $TOUCH -m $object 363} 364 365# 366# Unit testing function against write acl of a node 367# 368# $1: The given node, file/dir 369# $2: Execute user 370# $3: Expect value, default to be zero 371# 372function unit_writeacl 373{ 374 typeset object=$1 375 typeset user=$2 376 typeset expect=${3:-0} 377 378 verify_expect $expect $CHG_USR_EXEC $user chmod A+$TESTACL $object 379 verify_expect $expect $CHG_USR_EXEC $user chmod A+$TESTACL $object 380 verify_expect $expect $CHG_USR_EXEC $user chmod A0- $object 381 verify_expect $expect $CHG_USR_EXEC $user chmod A0- $object 382 oldmode=$(get_mode $object) 383 verify_expect $expect $CHG_USR_EXEC $user chmod $TESTMODE $object 384} 385 386# 387# Testing function to verify the given node is readonly 388# 389# $1: The given node, file/dir 390# 391function test_readonly 392{ 393 typeset object=$1 394 395 if [[ -z $object ]]; then 396 log_fail "Object($object) not defined." 397 fi 398 399 log_note "Testing readonly of $object" 400 401 for user in $ZFS_ACL_CUR_USER root $ZFS_ACL_STAFF2; do 402 if [[ -d $object ]]; then 403 log_must usr_exec chmod \ 404 A+user:$user:${ace_dir}:allow $object 405 else 406 log_must usr_exec chmod \ 407 A+user:$user:${ace_file}:allow $object 408 fi 409 410 log_must set_attribute $object "R" 411 412 unit_writefile $object $user 1 413 unit_writedir $object $user 414 unit_appenddata $object $user 1 415 416 if [[ -d $object ]]; then 417 unit_writexattr $object $user 418 else 419 unit_writexattr $object $user 1 420 fi 421 422 unit_accesstime $object $user 423 unit_updatetime $object $user 424 unit_writeacl $object $user 425 unit_deletecontent $object $user 426 unit_deletedata $object $user 427 428 if [[ -d $object ]] ;then 429 create_object "dir" $object $ZFS_ACL_CUR_USER 430 else 431 create_object "file" $object $ZFS_ACL_CUR_USER 432 fi 433 done 434} 435 436# 437# Testing function to verify the given node is immutable 438# 439# $1: The given node, file/dir 440# 441function test_immutable 442{ 443 typeset object=$1 444 445 if [[ -z $object ]]; then 446 log_fail "Object($object) not defined." 447 fi 448 449 log_note "Testing immutable of $object" 450 451 for user in $ZFS_ACL_CUR_USER root $ZFS_ACL_STAFF2; do 452 if [[ -d $object ]]; then 453 log_must usr_exec chmod \ 454 A+user:$user:${ace_dir}:allow $object 455 else 456 log_must usr_exec chmod \ 457 A+user:$user:${ace_file}:allow $object 458 fi 459 log_must set_attribute $object "i" 460 461 unit_writefile $object $user 1 462 unit_writedir $object $user 1 463 unit_appenddata $object $user 1 464 unit_writexattr $object $user 1 465 unit_accesstime $object $user 466 unit_updatetime $object $user 1 467 unit_writeacl $object $user 1 468 unit_deletecontent $object $user 1 469 unit_deletedata $object $user 1 470 471 if [[ -d $object ]] ;then 472 create_object "dir" $object $ZFS_ACL_CUR_USER 473 else 474 create_object "file" $object $ZFS_ACL_CUR_USER 475 fi 476 done 477} 478 479# 480# Testing function to verify the given node is nounlink 481# 482# $1: The given node, file/dir 483# 484function test_nounlink 485{ 486 typeset object=$1 487 488 if [[ -z $object ]]; then 489 log_fail "Object($object) not defined." 490 fi 491 492 $ECHO "Testing nounlink of $object" 493 494 for user in $ZFS_ACL_CUR_USER root $ZFS_ACL_STAFF2; do 495 if [[ -d $object ]]; then 496 log_must usr_exec chmod \ 497 A+user:$user:${ace_dir}:allow $object 498 else 499 log_must usr_exec chmod \ 500 A+user:$user:${ace_file}:allow $object 501 fi 502 log_must set_attribute $object "u" 503 504 unit_writefile $object $user 505 unit_writedir $object $user 506 unit_appenddata $object $user 507 unit_writexattr $object $user 508 unit_accesstime $object $user 509 unit_updatetime $object $user 510 unit_writeacl $object $user 511 unit_deletecontent $object $user 1 512 unit_deletedata $object $user 1 513 514 if [[ -d $object ]] ;then 515 create_object "dir" $object $ZFS_ACL_CUR_USER 516 else 517 create_object "file" $object $ZFS_ACL_CUR_USER 518 fi 519 done 520} 521 522# 523# Testing function to verify the given node is appendonly 524# 525# $1: The given node, file/dir 526# 527function test_appendonly 528{ 529 typeset object=$1 530 531 if [[ -z $object ]]; then 532 log_fail "Object($object) not defined." 533 fi 534 535 log_note "Testing appendonly of $object" 536 537 for user in $ZFS_ACL_CUR_USER root $ZFS_ACL_STAFF2; do 538 if [[ -d $object ]]; then 539 log_must usr_exec chmod \ 540 A+user:$user:${ace_dir}:allow $object 541 else 542 log_must usr_exec chmod \ 543 A+user:$user:${ace_file}:allow $object 544 fi 545 log_must set_attribute $object "a" 546 547 unit_writefile $object $user 1 548 unit_writedir $object $user 549 unit_appenddata $object $user 550 unit_writexattr $object $user 551 unit_accesstime $object $user 552 unit_updatetime $object $user 553 unit_writeacl $object $user 554 unit_deletecontent $object $user 555 unit_deletedata $object $user 556 557 if [[ -d $object ]] ;then 558 create_object "dir" $object $ZFS_ACL_CUR_USER 559 else 560 create_object "file" $object $ZFS_ACL_CUR_USER 561 fi 562 done 563} 564 565FILES="file.0 file.1" 566DIRS="dir.0 dir.1" 567XATTRS="attr.0 attr.1" 568FS="$TESTPOOL $TESTPOOL/$TESTFS" 569 570if is_global_zone ; then 571 ATTRS="R i u a" 572else 573 ATTRS="R" 574fi 575 576TESTFILE=$TMPDIR/tfile 577TESTDIR=tdir 578TESTATTR=tattr 579TESTACL=user:$ZFS_ACL_OTHER1:write_data:allow 580TESTMODE=777 581TESTSTR="ZFS test suites" 582 583ace_file="write_data/append_data/write_xattr/write_acl/write_attributes" 584ace_dir="add_file/add_subdirectory/${ace_file}" 585 586log_assert "Verify DOS & BSD'ish attributes will provide the " \ 587 "access limitation as expected." 588log_onexit cleanup 589 590$ECHO "$TESTSTR" > $TESTFILE 591 592typeset gobject 593typeset gattr 594for gattr in $ATTRS ; do 595 for fs in $FS ; do 596 mtpt=$(get_prop mountpoint $fs) 597 $CHMOD 777 $mtpt 598 for user in root $ZFS_ACL_STAFF1; do 599 log_must set_cur_usr $user 600 for file in $FILES ; do 601 gobject=$mtpt/$file 602 create_object "file" $gobject $ZFS_ACL_CUR_USER 603 test_wrapper $gobject $gattr 604 destroy_object $gobject 605 done 606 607 for dir in $DIRS ; do 608 gobject=$mtpt/$dir 609 create_object "dir" $gobject $ZFS_ACL_CUR_USER 610 test_wrapper $gobject $gattr 611 destroy_object $gobject 612 done 613 done 614 done 615done 616 617log_pass "DOS & BSD'ish attributes provide the access limitation as expected." 618