1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * General Structures Layout 28 * ------------------------- 29 * 30 * This is a simplified diagram showing the relationship between most of the 31 * main structures. 32 * 33 * +-------------------+ 34 * | SMB_INFO | 35 * +-------------------+ 36 * | 37 * | 38 * v 39 * +-------------------+ +-------------------+ +-------------------+ 40 * | SESSION |<----->| SESSION |......| SESSION | 41 * +-------------------+ +-------------------+ +-------------------+ 42 * | 43 * | 44 * v 45 * +-------------------+ +-------------------+ +-------------------+ 46 * | USER |<----->| USER |......| USER | 47 * +-------------------+ +-------------------+ +-------------------+ 48 * | 49 * | 50 * v 51 * +-------------------+ +-------------------+ +-------------------+ 52 * | TREE |<----->| TREE |......| TREE | 53 * +-------------------+ +-------------------+ +-------------------+ 54 * | | 55 * | | 56 * | v 57 * | +-------+ +-------+ +-------+ 58 * | | OFILE |<----->| OFILE |......| OFILE | 59 * | +-------+ +-------+ +-------+ 60 * | 61 * | 62 * v 63 * +-------+ +------+ +------+ 64 * | ODIR |<----->| ODIR |......| ODIR | 65 * +-------+ +------+ +------+ 66 * 67 * 68 * Ofile State Machine 69 * ------------------ 70 * 71 * +-------------------------+ T0 72 * | SMB_OFILE_STATE_OPEN |<----------- Creation/Allocation 73 * +-------------------------+ 74 * | 75 * | T1 76 * | 77 * v 78 * +-------------------------+ 79 * | SMB_OFILE_STATE_CLOSING | 80 * +-------------------------+ 81 * | 82 * | T2 83 * | 84 * v 85 * +-------------------------+ T3 86 * | SMB_OFILE_STATE_CLOSED |----------> Deletion/Free 87 * +-------------------------+ 88 * 89 * SMB_OFILE_STATE_OPEN 90 * 91 * While in this state: 92 * - The ofile is queued in the list of ofiles of its tree. 93 * - References will be given out if the ofile is looked up. 94 * 95 * SMB_OFILE_STATE_CLOSING 96 * 97 * While in this state: 98 * - The ofile is queued in the list of ofiles of its tree. 99 * - References will not be given out if the ofile is looked up. 100 * - The file is closed and the locks held are being released. 101 * - The resources associated with the ofile remain. 102 * 103 * SMB_OFILE_STATE_CLOSED 104 * 105 * While in this state: 106 * - The ofile is queued in the list of ofiles of its tree. 107 * - References will not be given out if the ofile is looked up. 108 * - The resources associated with the ofile remain. 109 * 110 * Transition T0 111 * 112 * This transition occurs in smb_ofile_open(). A new ofile is created and 113 * added to the list of ofiles of a tree. 114 * 115 * Transition T1 116 * 117 * This transition occurs in smb_ofile_close(). 118 * 119 * Transition T2 120 * 121 * This transition occurs in smb_ofile_release(). The resources associated 122 * with the ofile are freed as well as the ofile structure. For the 123 * transition to occur, the ofile must be in the SMB_OFILE_STATE_CLOSED 124 * state and the reference count be zero. 125 * 126 * Comments 127 * -------- 128 * 129 * The state machine of the ofile structures is controlled by 3 elements: 130 * - The list of ofiles of the tree it belongs to. 131 * - The mutex embedded in the structure itself. 132 * - The reference count. 133 * 134 * There's a mutex embedded in the ofile structure used to protect its fields 135 * and there's a lock embedded in the list of ofiles of a tree. To 136 * increment or to decrement the reference count the mutex must be entered. 137 * To insert the ofile into the list of ofiles of the tree and to remove 138 * the ofile from it, the lock must be entered in RW_WRITER mode. 139 * 140 * Rules of access to a ofile structure: 141 * 142 * 1) In order to avoid deadlocks, when both (mutex and lock of the ofile 143 * list) have to be entered, the lock must be entered first. 144 * 145 * 2) All actions applied to an ofile require a reference count. 146 * 147 * 3) There are 2 ways of getting a reference count. One is when the ofile 148 * is opened. The other one when the ofile is looked up. This translates 149 * into 2 functions: smb_ofile_open() and smb_ofile_lookup_by_fid(). 150 * 151 * It should be noted that the reference count of an ofile registers the 152 * number of references to the ofile in other structures (such as an smb 153 * request). The reference count is not incremented in these 2 instances: 154 * 155 * 1) The ofile is open. An ofile is anchored by his state. If there's 156 * no activity involving an ofile currently open, the reference count 157 * of that ofile is zero. 158 * 159 * 2) The ofile is queued in the list of ofiles of its tree. The fact of 160 * being queued in that list is NOT registered by incrementing the 161 * reference count. 162 */ 163 #include <smbsrv/smb_incl.h> 164 #include <smbsrv/smb_kproto.h> 165 #include <smbsrv/smb_fsops.h> 166 167 /* Static functions defined further down this file. */ 168 static void smb_ofile_delete(smb_ofile_t *of); 169 static smb_ofile_t *smb_ofile_close_and_next(smb_ofile_t *of); 170 171 /* 172 * smb_ofile_open 173 * 174 * 175 */ 176 smb_ofile_t * 177 smb_ofile_open( 178 smb_tree_t *tree, 179 smb_node_t *node, 180 uint16_t pid, 181 struct open_param *op, 182 uint16_t ftype, 183 uint32_t uniqid, 184 smb_error_t *err) 185 { 186 smb_ofile_t *of; 187 uint16_t fid; 188 189 if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) { 190 err->status = NT_STATUS_TOO_MANY_OPENED_FILES; 191 err->errcls = ERRDOS; 192 err->errcode = ERROR_TOO_MANY_OPEN_FILES; 193 return (NULL); 194 } 195 196 of = kmem_cache_alloc(tree->t_server->si_cache_ofile, KM_SLEEP); 197 bzero(of, sizeof (smb_ofile_t)); 198 of->f_magic = SMB_OFILE_MAGIC; 199 of->f_refcnt = 1; 200 of->f_fid = fid; 201 of->f_uniqid = uniqid; 202 of->f_opened_by_pid = pid; 203 of->f_granted_access = op->desired_access; 204 of->f_share_access = op->share_access; 205 of->f_create_options = op->create_options; 206 of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ? 207 smb_user_getprivcred(tree->t_user) : tree->t_user->u_cred; 208 crhold(of->f_cr); 209 of->f_ftype = ftype; 210 of->f_server = tree->t_server; 211 of->f_session = tree->t_user->u_session; 212 of->f_user = tree->t_user; 213 of->f_tree = tree; 214 of->f_node = node; 215 mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL); 216 of->f_state = SMB_OFILE_STATE_OPEN; 217 218 if (ftype == SMB_FTYPE_MESG_PIPE) { 219 of->f_pipe = kmem_zalloc(sizeof (smb_opipe_t), KM_SLEEP); 220 } else { 221 ASSERT(ftype == SMB_FTYPE_DISK); /* Regular file, not a pipe */ 222 ASSERT(node); 223 224 if (of->f_granted_access == FILE_EXECUTE) 225 of->f_flags |= SMB_OFLAGS_EXECONLY; 226 227 if (crgetuid(of->f_cr) == node->attr.sa_vattr.va_uid) { 228 /* 229 * Add this bit for the file's owner even if it's not 230 * specified in the request (Windows behavior). 231 */ 232 of->f_granted_access |= FILE_READ_ATTRIBUTES; 233 } 234 235 if (node->vp->v_type == VREG) { 236 of->f_mode = 237 smb_fsop_amask_to_omode(of->f_granted_access); 238 if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) { 239 of->f_magic = 0; 240 mutex_destroy(&of->f_mutex); 241 crfree(of->f_cr); 242 smb_idpool_free(&tree->t_fid_pool, of->f_fid); 243 kmem_cache_free(tree->t_server->si_cache_ofile, 244 of); 245 err->status = NT_STATUS_ACCESS_DENIED; 246 err->errcls = ERRDOS; 247 err->errcode = ERROR_ACCESS_DENIED; 248 return (NULL); 249 } 250 } 251 252 if (tree->t_flags & SMB_TREE_READONLY) 253 of->f_flags |= SMB_OFLAGS_READONLY; 254 255 if (op->created_readonly) 256 node->readonly_creator = of; 257 258 smb_node_inc_open_ofiles(node); 259 smb_node_add_ofile(node, of); 260 smb_node_ref(node); 261 } 262 smb_llist_enter(&tree->t_ofile_list, RW_WRITER); 263 smb_llist_insert_tail(&tree->t_ofile_list, of); 264 smb_llist_exit(&tree->t_ofile_list); 265 atomic_inc_32(&tree->t_server->sv_open_files); 266 atomic_inc_32(&of->f_session->s_file_cnt); 267 268 return (of); 269 } 270 271 /* 272 * smb_ofile_close 273 * 274 * 275 */ 276 void 277 smb_ofile_close( 278 smb_ofile_t *of, 279 uint32_t last_wtime) 280 { 281 ASSERT(of); 282 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 283 uint32_t flags = 0; 284 285 mutex_enter(&of->f_mutex); 286 ASSERT(of->f_refcnt); 287 switch (of->f_state) { 288 case SMB_OFILE_STATE_OPEN: { 289 290 of->f_state = SMB_OFILE_STATE_CLOSING; 291 mutex_exit(&of->f_mutex); 292 293 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 294 smb_opipe_close(of); 295 } else { 296 /* 297 * For files created readonly, propagate the readonly 298 * bit to the ofile now 299 */ 300 if (of->f_node->readonly_creator == of) { 301 of->f_node->attr.sa_dosattr |= 302 FILE_ATTRIBUTE_READONLY; 303 of->f_node->what |= SMB_AT_DOSATTR; 304 of->f_node->readonly_creator = NULL; 305 } 306 307 smb_ofile_close_timestamp_update(of, last_wtime); 308 (void) smb_sync_fsattr(NULL, of->f_cr, of->f_node); 309 if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) { 310 if (smb_tree_has_feature(of->f_tree, 311 SMB_TREE_CATIA)) { 312 flags |= SMB_CATIA; 313 } 314 (void) smb_node_set_delete_on_close(of->f_node, 315 of->f_cr, flags); 316 } 317 smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid); 318 smb_node_destroy_lock_by_ofile(of->f_node, of); 319 320 if (of->f_node->vp->v_type == VREG) 321 (void) smb_fsop_close(of->f_node, of->f_mode, 322 of->f_cr); 323 324 /* 325 * Cancel any notify change requests related 326 * to this open instance. 327 */ 328 if (of->f_node->flags & NODE_FLAGS_NOTIFY_CHANGE) 329 smb_process_file_notify_change_queue(of); 330 } 331 atomic_dec_32(&of->f_tree->t_server->sv_open_files); 332 333 mutex_enter(&of->f_mutex); 334 ASSERT(of->f_refcnt); 335 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING); 336 of->f_state = SMB_OFILE_STATE_CLOSED; 337 if (of->f_node != NULL) { 338 smb_node_dec_open_ofiles(of->f_node); 339 if (of->f_oplock_granted) { 340 smb_oplock_release(of->f_node, of); 341 of->f_oplock_granted = B_FALSE; 342 } 343 } 344 mutex_exit(&of->f_mutex); 345 return; 346 } 347 case SMB_OFILE_STATE_CLOSED: 348 case SMB_OFILE_STATE_CLOSING: 349 break; 350 351 default: 352 ASSERT(0); 353 break; 354 } 355 mutex_exit(&of->f_mutex); 356 } 357 358 /* 359 * smb_ofile_close_all 360 * 361 * 362 */ 363 void 364 smb_ofile_close_all( 365 smb_tree_t *tree) 366 { 367 smb_ofile_t *of; 368 369 ASSERT(tree); 370 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 371 372 smb_llist_enter(&tree->t_ofile_list, RW_READER); 373 of = smb_llist_head(&tree->t_ofile_list); 374 while (of) { 375 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 376 ASSERT(of->f_tree == tree); 377 of = smb_ofile_close_and_next(of); 378 } 379 smb_llist_exit(&tree->t_ofile_list); 380 } 381 382 /* 383 * smb_ofiles_close_by_pid 384 * 385 * 386 */ 387 void 388 smb_ofile_close_all_by_pid( 389 smb_tree_t *tree, 390 uint16_t pid) 391 { 392 smb_ofile_t *of; 393 394 ASSERT(tree); 395 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 396 397 smb_llist_enter(&tree->t_ofile_list, RW_READER); 398 of = smb_llist_head(&tree->t_ofile_list); 399 while (of) { 400 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 401 ASSERT(of->f_tree == tree); 402 if (of->f_opened_by_pid == pid) { 403 of = smb_ofile_close_and_next(of); 404 } else { 405 of = smb_llist_next(&tree->t_ofile_list, of); 406 } 407 } 408 smb_llist_exit(&tree->t_ofile_list); 409 } 410 411 /* 412 * smb_ofile_release 413 * 414 */ 415 void 416 smb_ofile_release( 417 smb_ofile_t *of) 418 { 419 ASSERT(of); 420 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 421 422 mutex_enter(&of->f_mutex); 423 if (of->f_oplock_exit) 424 if (smb_oplock_broadcast(of->f_node)) 425 of->f_oplock_exit = B_FALSE; 426 ASSERT(of->f_refcnt); 427 of->f_refcnt--; 428 switch (of->f_state) { 429 case SMB_OFILE_STATE_OPEN: 430 case SMB_OFILE_STATE_CLOSING: 431 break; 432 433 case SMB_OFILE_STATE_CLOSED: 434 if (of->f_refcnt == 0) { 435 mutex_exit(&of->f_mutex); 436 smb_ofile_delete(of); 437 return; 438 } 439 break; 440 441 default: 442 ASSERT(0); 443 break; 444 } 445 mutex_exit(&of->f_mutex); 446 } 447 448 /* 449 * smb_ofile_lookup_by_fid 450 * 451 * Find the open file whose fid matches the one specified in the request. 452 * If we can't find the fid or the shares (trees) don't match, we have a 453 * bad fid. 454 */ 455 smb_ofile_t * 456 smb_ofile_lookup_by_fid( 457 smb_tree_t *tree, 458 uint16_t fid) 459 { 460 smb_llist_t *of_list; 461 smb_ofile_t *of; 462 463 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 464 465 of_list = &tree->t_ofile_list; 466 467 smb_llist_enter(of_list, RW_READER); 468 of = smb_llist_head(of_list); 469 while (of) { 470 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 471 ASSERT(of->f_tree == tree); 472 if (of->f_fid == fid) { 473 mutex_enter(&of->f_mutex); 474 if (of->f_state != SMB_OFILE_STATE_OPEN) { 475 mutex_exit(&of->f_mutex); 476 smb_llist_exit(of_list); 477 return (NULL); 478 } 479 of->f_refcnt++; 480 mutex_exit(&of->f_mutex); 481 break; 482 } 483 of = smb_llist_next(of_list, of); 484 } 485 smb_llist_exit(of_list); 486 return (of); 487 } 488 489 /* 490 * smb_ofile_set_flags 491 * 492 * Return value: 493 * 494 * Current flags value 495 * 496 */ 497 void 498 smb_ofile_set_flags( 499 smb_ofile_t *of, 500 uint32_t flags) 501 { 502 ASSERT(of); 503 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 504 ASSERT(of->f_refcnt); 505 506 mutex_enter(&of->f_mutex); 507 of->f_flags |= flags; 508 mutex_exit(&of->f_mutex); 509 } 510 /* 511 * smb_ofile_seek 512 * 513 * Return value: 514 * 515 * 0 Success 516 * EINVAL Unknown mode 517 * EOVERFLOW offset too big 518 * 519 */ 520 int 521 smb_ofile_seek( 522 smb_ofile_t *of, 523 ushort_t mode, 524 int32_t off, 525 uint32_t *retoff) 526 { 527 u_offset_t newoff = 0; 528 int rc = 0; 529 530 ASSERT(of); 531 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 532 ASSERT(of->f_refcnt); 533 534 mutex_enter(&of->f_mutex); 535 switch (mode) { 536 case SMB_SEEK_SET: 537 if (off < 0) 538 newoff = 0; 539 else 540 newoff = (u_offset_t)off; 541 break; 542 543 case SMB_SEEK_CUR: 544 if (off < 0 && (-off) > of->f_seek_pos) 545 newoff = 0; 546 else 547 newoff = of->f_seek_pos + (u_offset_t)off; 548 break; 549 550 case SMB_SEEK_END: 551 if (off < 0 && (-off) > of->f_node->attr.sa_vattr.va_size) 552 newoff = 0; 553 else 554 newoff = of->f_node->attr.sa_vattr.va_size + 555 (u_offset_t)off; 556 break; 557 558 default: 559 mutex_exit(&of->f_mutex); 560 return (EINVAL); 561 } 562 563 /* 564 * See comments at the beginning of smb_seek.c. 565 * If the offset is greater than UINT_MAX, we will return an error. 566 */ 567 568 if (newoff > UINT_MAX) { 569 rc = EOVERFLOW; 570 } else { 571 of->f_seek_pos = newoff; 572 *retoff = (uint32_t)newoff; 573 } 574 mutex_exit(&of->f_mutex); 575 return (rc); 576 } 577 578 /* 579 * smb_ofile_close_timestamp_update 580 * 581 * The last_wtime is specified in the request received 582 * from the client. If it is neither 0 nor -1, this time 583 * should be used as the file's mtime. It must first be 584 * converted from the server's localtime (as received in 585 * the client's request) to GMT. 586 */ 587 void 588 smb_ofile_close_timestamp_update( 589 smb_ofile_t *of, 590 uint32_t last_wtime) 591 { 592 smb_node_t *node; 593 timestruc_t mtime, atime; 594 unsigned int what = 0; 595 596 mtime.tv_sec = 0; 597 mtime.tv_nsec = 0; 598 599 if (last_wtime != 0 && last_wtime != 0xFFFFFFFF) { 600 mtime.tv_sec = last_wtime + of->f_server->si_gmtoff; 601 what |= SMB_AT_MTIME; 602 } 603 604 /* 605 * NODE_FLAGS_SYNCATIME is set whenever something is 606 * written to a file. 607 */ 608 node = of->f_node; 609 if (node->flags & NODE_FLAGS_SYNCATIME) { 610 what |= SMB_AT_ATIME; 611 (void) microtime(&atime); 612 } 613 614 smb_node_set_time(node, 0, &mtime, &atime, 0, what); 615 } 616 617 /* 618 * smb_ofile_is_open 619 * 620 */ 621 boolean_t 622 smb_ofile_is_open(smb_ofile_t *of) 623 { 624 boolean_t rc = B_FALSE; 625 626 SMB_OFILE_VALID(of); 627 628 mutex_enter(&of->f_mutex); 629 if (of->f_state == SMB_OFILE_STATE_OPEN) { 630 rc = B_TRUE; 631 } 632 mutex_exit(&of->f_mutex); 633 return (rc); 634 } 635 636 void 637 smb_ofile_set_oplock_granted(smb_ofile_t *of) 638 { 639 SMB_OFILE_VALID(of); 640 mutex_enter(&of->f_mutex); 641 ASSERT(!of->f_oplock_granted); 642 of->f_oplock_granted = B_TRUE; 643 of->f_oplock_exit = B_TRUE; 644 mutex_exit(&of->f_mutex); 645 } 646 647 /* *************************** Static Functions ***************************** */ 648 649 /* 650 * smb_ofile_close_and_next 651 * 652 * This function closes the file passed in (if appropriate) and returns the 653 * next open file in the list of open files of the tree of the open file passed 654 * in. It requires that the list of open files of the tree be entered in 655 * RW_READER mode before being called. 656 */ 657 static smb_ofile_t * 658 smb_ofile_close_and_next( 659 smb_ofile_t *of) 660 { 661 smb_ofile_t *next_of; 662 smb_tree_t *tree; 663 664 ASSERT(of); 665 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 666 667 mutex_enter(&of->f_mutex); 668 switch (of->f_state) { 669 case SMB_OFILE_STATE_OPEN: 670 /* The file is still open. */ 671 of->f_refcnt++; 672 ASSERT(of->f_refcnt); 673 tree = of->f_tree; 674 mutex_exit(&of->f_mutex); 675 smb_llist_exit(&of->f_tree->t_ofile_list); 676 smb_ofile_close(of, 0); 677 smb_ofile_release(of); 678 smb_llist_enter(&tree->t_ofile_list, RW_READER); 679 next_of = smb_llist_head(&tree->t_ofile_list); 680 break; 681 case SMB_OFILE_STATE_CLOSING: 682 case SMB_OFILE_STATE_CLOSED: 683 /* 684 * The ofile exists but is closed or 685 * in the process being closed. 686 */ 687 mutex_exit(&of->f_mutex); 688 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 689 break; 690 default: 691 ASSERT(0); 692 mutex_exit(&of->f_mutex); 693 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 694 break; 695 } 696 return (next_of); 697 } 698 699 /* 700 * smb_ofile_delete 701 * 702 * 703 */ 704 static void 705 smb_ofile_delete( 706 smb_ofile_t *of) 707 { 708 ASSERT(of); 709 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 710 ASSERT(of->f_refcnt == 0); 711 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); 712 713 /* 714 * Let's remove the ofile from the list of ofiles of the tree. This has 715 * to be done before any resources associated with the ofile are 716 * released. 717 */ 718 smb_llist_enter(&of->f_tree->t_ofile_list, RW_WRITER); 719 smb_llist_remove(&of->f_tree->t_ofile_list, of); 720 smb_llist_exit(&of->f_tree->t_ofile_list); 721 atomic_dec_32(&of->f_session->s_file_cnt); 722 723 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 724 kmem_free(of->f_pipe, sizeof (smb_opipe_t)); 725 of->f_pipe = NULL; 726 } else { 727 ASSERT(of->f_ftype == SMB_FTYPE_DISK); 728 ASSERT(of->f_node != NULL); 729 smb_node_rem_ofile(of->f_node, of); 730 smb_node_release(of->f_node); 731 } 732 733 of->f_magic = (uint32_t)~SMB_OFILE_MAGIC; 734 mutex_destroy(&of->f_mutex); 735 crfree(of->f_cr); 736 smb_idpool_free(&of->f_tree->t_fid_pool, of->f_fid); 737 kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of); 738 } 739 740 /* 741 * smb_ofile_access 742 * 743 * This function will check to see if the access requested is granted. 744 * Returns NT status codes. 745 */ 746 uint32_t 747 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access) 748 { 749 750 if ((of == NULL) || (cr == kcred)) 751 return (NT_STATUS_SUCCESS); 752 753 /* 754 * If the request is for something 755 * I don't grant it is an error 756 */ 757 if (~(of->f_granted_access) & access) { 758 if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) && 759 (access & ACCESS_SYSTEM_SECURITY)) { 760 return (NT_STATUS_PRIVILEGE_NOT_HELD); 761 } 762 return (NT_STATUS_ACCESS_DENIED); 763 } 764 765 return (NT_STATUS_SUCCESS); 766 } 767 768 769 /* 770 * smb_ofile_open_check 771 * 772 * check file sharing rules for current open request 773 * against existing open instances of the same file 774 * 775 * Returns NT_STATUS_SHARING_VIOLATION if there is any 776 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 777 */ 778 uint32_t 779 smb_ofile_open_check( 780 smb_ofile_t *of, 781 cred_t *cr, 782 uint32_t desired_access, 783 uint32_t share_access) 784 { 785 smb_node_t *node; 786 787 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 788 789 node = of->f_node; 790 791 mutex_enter(&of->f_mutex); 792 793 if (of->f_state != SMB_OFILE_STATE_OPEN) { 794 mutex_exit(&of->f_mutex); 795 return (NT_STATUS_INVALID_HANDLE); 796 } 797 798 /* 799 * It appears that share modes are not relevant to 800 * directories, but this check will remain as it is not 801 * clear whether it was originally put here for a reason. 802 */ 803 if (node->attr.sa_vattr.va_type == VDIR) { 804 if (SMB_DENY_RW(of->f_share_access) && 805 (node->n_orig_uid != crgetuid(cr))) { 806 mutex_exit(&of->f_mutex); 807 return (NT_STATUS_SHARING_VIOLATION); 808 } 809 810 mutex_exit(&of->f_mutex); 811 return (NT_STATUS_SUCCESS); 812 } 813 814 /* if it's just meta data */ 815 if ((of->f_granted_access & FILE_DATA_ALL) == 0) { 816 mutex_exit(&of->f_mutex); 817 return (NT_STATUS_SUCCESS); 818 } 819 820 /* 821 * Check requested share access against the 822 * open granted (desired) access 823 */ 824 if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) { 825 mutex_exit(&of->f_mutex); 826 return (NT_STATUS_SHARING_VIOLATION); 827 } 828 829 if (SMB_DENY_READ(share_access) && 830 (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) { 831 mutex_exit(&of->f_mutex); 832 return (NT_STATUS_SHARING_VIOLATION); 833 } 834 835 if (SMB_DENY_WRITE(share_access) && 836 (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 837 mutex_exit(&of->f_mutex); 838 return (NT_STATUS_SHARING_VIOLATION); 839 } 840 841 /* check requested desired access against the open share access */ 842 if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) { 843 mutex_exit(&of->f_mutex); 844 return (NT_STATUS_SHARING_VIOLATION); 845 } 846 847 if (SMB_DENY_READ(of->f_share_access) && 848 (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) { 849 mutex_exit(&of->f_mutex); 850 return (NT_STATUS_SHARING_VIOLATION); 851 } 852 853 if (SMB_DENY_WRITE(of->f_share_access) && 854 (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 855 mutex_exit(&of->f_mutex); 856 return (NT_STATUS_SHARING_VIOLATION); 857 } 858 859 mutex_exit(&of->f_mutex); 860 return (NT_STATUS_SUCCESS); 861 } 862 863 /* 864 * smb_ofile_rename_check 865 * 866 * An open file can be renamed if 867 * 868 * 1. isn't opened for data writing or deleting 869 * 870 * 2. Opened with "Deny Delete" share mode 871 * But not opened for data reading or executing 872 * (opened for accessing meta data) 873 */ 874 875 uint32_t 876 smb_ofile_rename_check(smb_ofile_t *of) 877 { 878 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 879 880 mutex_enter(&of->f_mutex); 881 882 if (of->f_state != SMB_OFILE_STATE_OPEN) { 883 mutex_exit(&of->f_mutex); 884 return (NT_STATUS_INVALID_HANDLE); 885 } 886 887 if (of->f_granted_access & 888 (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { 889 mutex_exit(&of->f_mutex); 890 return (NT_STATUS_SHARING_VIOLATION); 891 } 892 893 if ((of->f_share_access & FILE_SHARE_DELETE) == 0) { 894 if (of->f_granted_access & 895 (FILE_READ_DATA | FILE_EXECUTE)) { 896 mutex_exit(&of->f_mutex); 897 return (NT_STATUS_SHARING_VIOLATION); 898 } 899 } 900 901 mutex_exit(&of->f_mutex); 902 return (NT_STATUS_SUCCESS); 903 } 904 905 /* 906 * smb_ofile_delete_check 907 * 908 * An open file can be deleted only if opened for 909 * accessing meta data. Share modes aren't important 910 * in this case. 911 * 912 * NOTE: there is another mechanism for deleting an 913 * open file that NT clients usually use. 914 * That's setting "Delete on close" flag for an open 915 * file. In this way the file will be deleted after 916 * last close. This flag can be set by SmbTrans2SetFileInfo 917 * with FILE_DISPOSITION_INFO information level. 918 * For setting this flag, the file should be opened by 919 * DELETE access in the FID that is passed in the Trans2 920 * request. 921 */ 922 923 uint32_t 924 smb_ofile_delete_check(smb_ofile_t *of) 925 { 926 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 927 928 mutex_enter(&of->f_mutex); 929 930 if (of->f_state != SMB_OFILE_STATE_OPEN) { 931 mutex_exit(&of->f_mutex); 932 return (NT_STATUS_INVALID_HANDLE); 933 } 934 935 if (of->f_granted_access & 936 (FILE_READ_DATA | FILE_WRITE_DATA | 937 FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) { 938 mutex_exit(&of->f_mutex); 939 return (NT_STATUS_SHARING_VIOLATION); 940 } 941 942 mutex_exit(&of->f_mutex); 943 return (NT_STATUS_SUCCESS); 944 } 945 946 cred_t * 947 smb_ofile_getcred(smb_ofile_t *of) 948 { 949 return (of->f_cr); 950 } 951 952 /* 953 * smb_ofile_set_delete_on_close 954 * 955 * Set the DeleteOnClose flag on the smb file. When the file is closed, 956 * the flag will be transferred to the smb node, which will commit the 957 * delete operation and inhibit subsequent open requests. 958 * 959 * When DeleteOnClose is set on an smb_node, the common open code will 960 * reject subsequent open requests for the file. Observation of Windows 961 * 2000 indicates that subsequent opens should be allowed (assuming 962 * there would be no sharing violation) until the file is closed using 963 * the fid on which the DeleteOnClose was requested. 964 */ 965 void 966 smb_ofile_set_delete_on_close(smb_ofile_t *of) 967 { 968 mutex_enter(&of->f_mutex); 969 of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE; 970 mutex_exit(&of->f_mutex); 971 } 972