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 static void smb_ofile_set_close_attrs(smb_ofile_t *, uint32_t); 171 172 /* 173 * smb_ofile_open 174 */ 175 smb_ofile_t * 176 smb_ofile_open( 177 smb_tree_t *tree, 178 smb_node_t *node, 179 uint16_t pid, 180 struct open_param *op, 181 uint16_t ftype, 182 uint32_t uniqid, 183 smb_error_t *err) 184 { 185 smb_ofile_t *of; 186 uint16_t fid; 187 smb_attr_t attr; 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 of->f_explicit_times = 0; 216 mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL); 217 of->f_state = SMB_OFILE_STATE_OPEN; 218 219 220 if (ftype == SMB_FTYPE_MESG_PIPE) { 221 of->f_pipe = kmem_zalloc(sizeof (smb_opipe_t), KM_SLEEP); 222 } else { 223 ASSERT(ftype == SMB_FTYPE_DISK); /* Regular file, not a pipe */ 224 ASSERT(node); 225 226 if (of->f_granted_access == FILE_EXECUTE) 227 of->f_flags |= SMB_OFLAGS_EXECONLY; 228 229 bzero(&attr, sizeof (smb_attr_t)); 230 attr.sa_mask |= SMB_AT_UID; 231 if (smb_fsop_getattr(NULL, kcred, node, &attr) != 0) { 232 of->f_magic = 0; 233 mutex_destroy(&of->f_mutex); 234 crfree(of->f_cr); 235 smb_idpool_free(&tree->t_fid_pool, of->f_fid); 236 kmem_cache_free(tree->t_server->si_cache_ofile, of); 237 err->status = NT_STATUS_INTERNAL_ERROR; 238 err->errcls = ERRDOS; 239 err->errcode = ERROR_INTERNAL_ERROR; 240 return (NULL); 241 } 242 if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) { 243 /* 244 * Add this bit for the file's owner even if it's not 245 * specified in the request (Windows behavior). 246 */ 247 of->f_granted_access |= FILE_READ_ATTRIBUTES; 248 } 249 250 if (node->vp->v_type == VREG) { 251 of->f_mode = 252 smb_fsop_amask_to_omode(of->f_granted_access); 253 if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) { 254 of->f_magic = 0; 255 mutex_destroy(&of->f_mutex); 256 crfree(of->f_cr); 257 smb_idpool_free(&tree->t_fid_pool, of->f_fid); 258 kmem_cache_free(tree->t_server->si_cache_ofile, 259 of); 260 err->status = NT_STATUS_ACCESS_DENIED; 261 err->errcls = ERRDOS; 262 err->errcode = ERROR_ACCESS_DENIED; 263 return (NULL); 264 } 265 } 266 267 if (tree->t_flags & SMB_TREE_READONLY) 268 of->f_flags |= SMB_OFLAGS_READONLY; 269 270 if (op->created_readonly) 271 node->readonly_creator = of; 272 273 smb_node_inc_open_ofiles(node); 274 smb_node_add_ofile(node, of); 275 smb_node_ref(node); 276 } 277 smb_llist_enter(&tree->t_ofile_list, RW_WRITER); 278 smb_llist_insert_tail(&tree->t_ofile_list, of); 279 smb_llist_exit(&tree->t_ofile_list); 280 atomic_inc_32(&tree->t_server->sv_open_files); 281 atomic_inc_32(&of->f_session->s_file_cnt); 282 283 return (of); 284 } 285 286 /* 287 * smb_ofile_close 288 */ 289 void 290 smb_ofile_close(smb_ofile_t *of, uint32_t last_wtime) 291 { 292 ASSERT(of); 293 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 294 uint32_t flags = 0; 295 296 mutex_enter(&of->f_mutex); 297 ASSERT(of->f_refcnt); 298 switch (of->f_state) { 299 case SMB_OFILE_STATE_OPEN: { 300 301 of->f_state = SMB_OFILE_STATE_CLOSING; 302 mutex_exit(&of->f_mutex); 303 304 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 305 smb_opipe_close(of); 306 } else { 307 smb_ofile_set_close_attrs(of, last_wtime); 308 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 smb_attr_t attr; 530 531 ASSERT(of); 532 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 533 ASSERT(of->f_refcnt); 534 535 mutex_enter(&of->f_mutex); 536 switch (mode) { 537 case SMB_SEEK_SET: 538 if (off < 0) 539 newoff = 0; 540 else 541 newoff = (u_offset_t)off; 542 break; 543 544 case SMB_SEEK_CUR: 545 if (off < 0 && (-off) > of->f_seek_pos) 546 newoff = 0; 547 else 548 newoff = of->f_seek_pos + (u_offset_t)off; 549 break; 550 551 case SMB_SEEK_END: 552 bzero(&attr, sizeof (smb_attr_t)); 553 attr.sa_mask |= SMB_AT_SIZE; 554 rc = smb_fsop_getattr(NULL, kcred, of->f_node, &attr); 555 if (rc != 0) { 556 mutex_exit(&of->f_mutex); 557 return (rc); 558 } 559 if (off < 0 && (-off) > attr.sa_vattr.va_size) 560 newoff = 0; 561 else 562 newoff = attr.sa_vattr.va_size + (u_offset_t)off; 563 break; 564 565 default: 566 mutex_exit(&of->f_mutex); 567 return (EINVAL); 568 } 569 570 /* 571 * See comments at the beginning of smb_seek.c. 572 * If the offset is greater than UINT_MAX, we will return an error. 573 */ 574 575 if (newoff > UINT_MAX) { 576 rc = EOVERFLOW; 577 } else { 578 of->f_seek_pos = newoff; 579 *retoff = (uint32_t)newoff; 580 } 581 mutex_exit(&of->f_mutex); 582 return (rc); 583 } 584 585 /* 586 * smb_ofile_is_open 587 */ 588 boolean_t 589 smb_ofile_is_open(smb_ofile_t *of) 590 { 591 boolean_t rc = B_FALSE; 592 593 SMB_OFILE_VALID(of); 594 595 mutex_enter(&of->f_mutex); 596 if (of->f_state == SMB_OFILE_STATE_OPEN) { 597 rc = B_TRUE; 598 } 599 mutex_exit(&of->f_mutex); 600 return (rc); 601 } 602 603 void 604 smb_ofile_set_oplock_granted(smb_ofile_t *of) 605 { 606 SMB_OFILE_VALID(of); 607 mutex_enter(&of->f_mutex); 608 ASSERT(!of->f_oplock_granted); 609 of->f_oplock_granted = B_TRUE; 610 of->f_oplock_exit = B_TRUE; 611 mutex_exit(&of->f_mutex); 612 } 613 614 /* 615 * smb_ofile_pending_write_time 616 * 617 * Flag write times as pending - to be set on close, setattr 618 * or delayed write timer. 619 */ 620 void 621 smb_ofile_set_write_time_pending(smb_ofile_t *of) 622 { 623 SMB_OFILE_VALID(of); 624 mutex_enter(&of->f_mutex); 625 of->f_flags |= SMB_OFLAGS_TIMESTAMPS_PENDING; 626 mutex_exit(&of->f_mutex); 627 } 628 629 boolean_t 630 smb_ofile_write_time_pending(smb_ofile_t *of) 631 { 632 boolean_t rc = B_FALSE; 633 634 SMB_OFILE_VALID(of); 635 mutex_enter(&of->f_mutex); 636 if (of->f_flags & SMB_OFLAGS_TIMESTAMPS_PENDING) 637 rc = B_TRUE; 638 mutex_exit(&of->f_mutex); 639 640 return (rc); 641 } 642 643 /* 644 * smb_ofile_set_explicit_time_flag 645 * 646 * Note the timestamps specified in "what", as having been 647 * explicity set for the ofile. Also clear the flag for pending 648 * timestamps as the pending timestamps will have been applied 649 * by the explicit set. 650 */ 651 void 652 smb_ofile_set_explicit_times(smb_ofile_t *of, uint32_t what) 653 { 654 SMB_OFILE_VALID(of); 655 mutex_enter(&of->f_mutex); 656 of->f_flags &= ~SMB_OFLAGS_TIMESTAMPS_PENDING; 657 of->f_explicit_times |= (what & SMB_AT_TIMES); 658 mutex_exit(&of->f_mutex); 659 } 660 661 uint32_t 662 smb_ofile_explicit_times(smb_ofile_t *of) 663 { 664 uint32_t rc; 665 666 SMB_OFILE_VALID(of); 667 mutex_enter(&of->f_mutex); 668 rc = of->f_explicit_times; 669 mutex_exit(&of->f_mutex); 670 671 return (rc); 672 } 673 674 /* *************************** Static Functions ***************************** */ 675 676 /* 677 * smb_ofile_set_close_attrs 678 * 679 * Updates timestamps, size and readonly bit. 680 * The last_wtime is specified in the request received 681 * from the client. If it is neither 0 nor -1, this time 682 * should be used as the file's mtime. It must first be 683 * converted from the server's localtime (as received in 684 * the client's request) to GMT. 685 * 686 * Call smb_node_setattr even if no attributes are being 687 * explicitly set, to set any pending attributes. 688 */ 689 static void 690 smb_ofile_set_close_attrs(smb_ofile_t *of, uint32_t last_wtime) 691 { 692 smb_node_t *node = of->f_node; 693 smb_attr_t attr; 694 695 bzero(&attr, sizeof (smb_attr_t)); 696 697 /* For files created readonly, propagate readonly bit */ 698 if (node->readonly_creator == of) { 699 attr.sa_mask |= SMB_AT_DOSATTR; 700 if (smb_fsop_getattr(NULL, kcred, node, &attr) && 701 (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) { 702 attr.sa_mask = 0; 703 } else { 704 attr.sa_dosattr |= FILE_ATTRIBUTE_READONLY; 705 } 706 707 node->readonly_creator = NULL; 708 } 709 710 /* apply last_wtime if specified */ 711 if (last_wtime != 0 && last_wtime != 0xFFFFFFFF) { 712 attr.sa_vattr.va_mtime.tv_sec = 713 last_wtime + of->f_server->si_gmtoff; 714 attr.sa_mask |= SMB_AT_MTIME; 715 } 716 717 (void) smb_node_setattr(NULL, node, of->f_cr, of, &attr); 718 } 719 720 /* 721 * smb_ofile_close_and_next 722 * 723 * This function closes the file passed in (if appropriate) and returns the 724 * next open file in the list of open files of the tree of the open file passed 725 * in. It requires that the list of open files of the tree be entered in 726 * RW_READER mode before being called. 727 */ 728 static smb_ofile_t * 729 smb_ofile_close_and_next(smb_ofile_t *of) 730 { 731 smb_ofile_t *next_of; 732 smb_tree_t *tree; 733 734 ASSERT(of); 735 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 736 737 mutex_enter(&of->f_mutex); 738 switch (of->f_state) { 739 case SMB_OFILE_STATE_OPEN: 740 /* The file is still open. */ 741 of->f_refcnt++; 742 ASSERT(of->f_refcnt); 743 tree = of->f_tree; 744 mutex_exit(&of->f_mutex); 745 smb_llist_exit(&of->f_tree->t_ofile_list); 746 smb_ofile_close(of, 0); 747 smb_ofile_release(of); 748 smb_llist_enter(&tree->t_ofile_list, RW_READER); 749 next_of = smb_llist_head(&tree->t_ofile_list); 750 break; 751 case SMB_OFILE_STATE_CLOSING: 752 case SMB_OFILE_STATE_CLOSED: 753 /* 754 * The ofile exists but is closed or 755 * in the process being closed. 756 */ 757 mutex_exit(&of->f_mutex); 758 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 759 break; 760 default: 761 ASSERT(0); 762 mutex_exit(&of->f_mutex); 763 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 764 break; 765 } 766 return (next_of); 767 } 768 769 /* 770 * smb_ofile_delete 771 * 772 * 773 */ 774 static void 775 smb_ofile_delete(smb_ofile_t *of) 776 { 777 ASSERT(of); 778 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 779 ASSERT(of->f_refcnt == 0); 780 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); 781 782 /* 783 * Let's remove the ofile from the list of ofiles of the tree. This has 784 * to be done before any resources associated with the ofile are 785 * released. 786 */ 787 smb_llist_enter(&of->f_tree->t_ofile_list, RW_WRITER); 788 smb_llist_remove(&of->f_tree->t_ofile_list, of); 789 smb_llist_exit(&of->f_tree->t_ofile_list); 790 atomic_dec_32(&of->f_session->s_file_cnt); 791 792 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 793 kmem_free(of->f_pipe, sizeof (smb_opipe_t)); 794 of->f_pipe = NULL; 795 } else { 796 ASSERT(of->f_ftype == SMB_FTYPE_DISK); 797 ASSERT(of->f_node != NULL); 798 smb_node_rem_ofile(of->f_node, of); 799 smb_node_release(of->f_node); 800 } 801 802 of->f_magic = (uint32_t)~SMB_OFILE_MAGIC; 803 mutex_destroy(&of->f_mutex); 804 crfree(of->f_cr); 805 smb_idpool_free(&of->f_tree->t_fid_pool, of->f_fid); 806 kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of); 807 } 808 809 /* 810 * smb_ofile_access 811 * 812 * This function will check to see if the access requested is granted. 813 * Returns NT status codes. 814 */ 815 uint32_t 816 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access) 817 { 818 819 if ((of == NULL) || (cr == kcred)) 820 return (NT_STATUS_SUCCESS); 821 822 /* 823 * If the request is for something 824 * I don't grant it is an error 825 */ 826 if (~(of->f_granted_access) & access) { 827 if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) && 828 (access & ACCESS_SYSTEM_SECURITY)) { 829 return (NT_STATUS_PRIVILEGE_NOT_HELD); 830 } 831 return (NT_STATUS_ACCESS_DENIED); 832 } 833 834 return (NT_STATUS_SUCCESS); 835 } 836 837 838 /* 839 * smb_ofile_open_check 840 * 841 * check file sharing rules for current open request 842 * against existing open instances of the same file 843 * 844 * Returns NT_STATUS_SHARING_VIOLATION if there is any 845 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 846 */ 847 uint32_t 848 smb_ofile_open_check( 849 smb_ofile_t *of, 850 cred_t *cr, 851 uint32_t desired_access, 852 uint32_t share_access) 853 { 854 smb_node_t *node; 855 856 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 857 858 node = of->f_node; 859 860 mutex_enter(&of->f_mutex); 861 862 if (of->f_state != SMB_OFILE_STATE_OPEN) { 863 mutex_exit(&of->f_mutex); 864 return (NT_STATUS_INVALID_HANDLE); 865 } 866 867 /* 868 * It appears that share modes are not relevant to 869 * directories, but this check will remain as it is not 870 * clear whether it was originally put here for a reason. 871 */ 872 if (smb_node_is_dir(node)) { 873 if (SMB_DENY_RW(of->f_share_access) && 874 (node->n_orig_uid != crgetuid(cr))) { 875 mutex_exit(&of->f_mutex); 876 return (NT_STATUS_SHARING_VIOLATION); 877 } 878 879 mutex_exit(&of->f_mutex); 880 return (NT_STATUS_SUCCESS); 881 } 882 883 /* if it's just meta data */ 884 if ((of->f_granted_access & FILE_DATA_ALL) == 0) { 885 mutex_exit(&of->f_mutex); 886 return (NT_STATUS_SUCCESS); 887 } 888 889 /* 890 * Check requested share access against the 891 * open granted (desired) access 892 */ 893 if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) { 894 mutex_exit(&of->f_mutex); 895 return (NT_STATUS_SHARING_VIOLATION); 896 } 897 898 if (SMB_DENY_READ(share_access) && 899 (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) { 900 mutex_exit(&of->f_mutex); 901 return (NT_STATUS_SHARING_VIOLATION); 902 } 903 904 if (SMB_DENY_WRITE(share_access) && 905 (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 906 mutex_exit(&of->f_mutex); 907 return (NT_STATUS_SHARING_VIOLATION); 908 } 909 910 /* check requested desired access against the open share access */ 911 if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) { 912 mutex_exit(&of->f_mutex); 913 return (NT_STATUS_SHARING_VIOLATION); 914 } 915 916 if (SMB_DENY_READ(of->f_share_access) && 917 (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) { 918 mutex_exit(&of->f_mutex); 919 return (NT_STATUS_SHARING_VIOLATION); 920 } 921 922 if (SMB_DENY_WRITE(of->f_share_access) && 923 (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 924 mutex_exit(&of->f_mutex); 925 return (NT_STATUS_SHARING_VIOLATION); 926 } 927 928 mutex_exit(&of->f_mutex); 929 return (NT_STATUS_SUCCESS); 930 } 931 932 /* 933 * smb_ofile_rename_check 934 * 935 * An open file can be renamed if 936 * 937 * 1. isn't opened for data writing or deleting 938 * 939 * 2. Opened with "Deny Delete" share mode 940 * But not opened for data reading or executing 941 * (opened for accessing meta data) 942 */ 943 944 uint32_t 945 smb_ofile_rename_check(smb_ofile_t *of) 946 { 947 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 948 949 mutex_enter(&of->f_mutex); 950 951 if (of->f_state != SMB_OFILE_STATE_OPEN) { 952 mutex_exit(&of->f_mutex); 953 return (NT_STATUS_INVALID_HANDLE); 954 } 955 956 if (of->f_granted_access & 957 (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { 958 mutex_exit(&of->f_mutex); 959 return (NT_STATUS_SHARING_VIOLATION); 960 } 961 962 if ((of->f_share_access & FILE_SHARE_DELETE) == 0) { 963 if (of->f_granted_access & 964 (FILE_READ_DATA | FILE_EXECUTE)) { 965 mutex_exit(&of->f_mutex); 966 return (NT_STATUS_SHARING_VIOLATION); 967 } 968 } 969 970 mutex_exit(&of->f_mutex); 971 return (NT_STATUS_SUCCESS); 972 } 973 974 /* 975 * smb_ofile_delete_check 976 * 977 * An open file can be deleted only if opened for 978 * accessing meta data. Share modes aren't important 979 * in this case. 980 * 981 * NOTE: there is another mechanism for deleting an 982 * open file that NT clients usually use. 983 * That's setting "Delete on close" flag for an open 984 * file. In this way the file will be deleted after 985 * last close. This flag can be set by SmbTrans2SetFileInfo 986 * with FILE_DISPOSITION_INFO information level. 987 * For setting this flag, the file should be opened by 988 * DELETE access in the FID that is passed in the Trans2 989 * request. 990 */ 991 992 uint32_t 993 smb_ofile_delete_check(smb_ofile_t *of) 994 { 995 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 996 997 mutex_enter(&of->f_mutex); 998 999 if (of->f_state != SMB_OFILE_STATE_OPEN) { 1000 mutex_exit(&of->f_mutex); 1001 return (NT_STATUS_INVALID_HANDLE); 1002 } 1003 1004 if (of->f_granted_access & 1005 (FILE_READ_DATA | FILE_WRITE_DATA | 1006 FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) { 1007 mutex_exit(&of->f_mutex); 1008 return (NT_STATUS_SHARING_VIOLATION); 1009 } 1010 1011 mutex_exit(&of->f_mutex); 1012 return (NT_STATUS_SUCCESS); 1013 } 1014 1015 cred_t * 1016 smb_ofile_getcred(smb_ofile_t *of) 1017 { 1018 return (of->f_cr); 1019 } 1020 1021 /* 1022 * smb_ofile_set_delete_on_close 1023 * 1024 * Set the DeleteOnClose flag on the smb file. When the file is closed, 1025 * the flag will be transferred to the smb node, which will commit the 1026 * delete operation and inhibit subsequent open requests. 1027 * 1028 * When DeleteOnClose is set on an smb_node, the common open code will 1029 * reject subsequent open requests for the file. Observation of Windows 1030 * 2000 indicates that subsequent opens should be allowed (assuming 1031 * there would be no sharing violation) until the file is closed using 1032 * the fid on which the DeleteOnClose was requested. 1033 */ 1034 void 1035 smb_ofile_set_delete_on_close(smb_ofile_t *of) 1036 { 1037 mutex_enter(&of->f_mutex); 1038 of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE; 1039 mutex_exit(&of->f_mutex); 1040 } 1041