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