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 /* 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 if (crgetuid(of->f_cr) == node->attr.sa_vattr.va_uid) { 224 /* 225 * Add this bit for the file's owner even if it's not 226 * specified in the request (Windows behavior). 227 */ 228 of->f_granted_access |= FILE_READ_ATTRIBUTES; 229 } 230 231 if (node->vp->v_type == VREG) { 232 of->f_mode = 233 smb_fsop_amask_to_omode(of->f_granted_access); 234 if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) { 235 of->f_magic = 0; 236 mutex_destroy(&of->f_mutex); 237 crfree(of->f_cr); 238 smb_idpool_free(&tree->t_fid_pool, of->f_fid); 239 kmem_cache_free(tree->t_server->si_cache_ofile, 240 of); 241 err->status = NT_STATUS_ACCESS_DENIED; 242 err->errcls = ERRDOS; 243 err->errcode = ERROR_ACCESS_DENIED; 244 return (NULL); 245 } 246 } 247 248 if (tree->t_flags & SMB_TREE_READONLY) 249 of->f_flags |= SMB_OFLAGS_READONLY; 250 251 if (op->created_readonly) 252 node->readonly_creator = of; 253 254 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 255 smb_llist_insert_tail(&node->n_ofile_list, of); 256 smb_llist_exit(&node->n_ofile_list); 257 } 258 smb_llist_enter(&tree->t_ofile_list, RW_WRITER); 259 smb_llist_insert_tail(&tree->t_ofile_list, of); 260 smb_llist_exit(&tree->t_ofile_list); 261 atomic_inc_32(&tree->t_server->sv_open_files); 262 atomic_inc_32(&of->f_session->s_file_cnt); 263 264 return (of); 265 } 266 267 /* 268 * smb_ofile_close 269 * 270 * 271 */ 272 void 273 smb_ofile_close( 274 smb_ofile_t *of, 275 uint32_t last_wtime) 276 { 277 ASSERT(of); 278 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 279 280 mutex_enter(&of->f_mutex); 281 ASSERT(of->f_refcnt); 282 switch (of->f_state) { 283 case SMB_OFILE_STATE_OPEN: { 284 285 of->f_state = SMB_OFILE_STATE_CLOSING; 286 mutex_exit(&of->f_mutex); 287 288 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 289 smb_opipe_close(of); 290 } else { 291 /* 292 * For files created readonly, propagate the readonly 293 * bit to the ofile now 294 */ 295 296 if (of->f_node->readonly_creator == of) { 297 of->f_node->attr.sa_dosattr |= 298 FILE_ATTRIBUTE_READONLY; 299 of->f_node->what |= SMB_AT_DOSATTR; 300 of->f_node->readonly_creator = NULL; 301 } 302 303 smb_ofile_close_timestamp_update(of, last_wtime); 304 (void) smb_sync_fsattr(NULL, of->f_cr, of->f_node); 305 smb_commit_delete_on_close(of); 306 smb_oplock_release(of->f_node, B_FALSE); 307 smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid); 308 smb_node_destroy_lock_by_ofile(of->f_node, of); 309 310 if (of->f_node->vp->v_type == VREG) 311 (void) smb_fsop_close(of->f_node, of->f_mode, 312 of->f_cr); 313 314 /* 315 * Cancel any notify change requests related 316 * to this open instance. 317 */ 318 if (of->f_node->flags & NODE_FLAGS_NOTIFY_CHANGE) 319 smb_process_file_notify_change_queue(of); 320 } 321 atomic_dec_32(&of->f_tree->t_server->sv_open_files); 322 323 mutex_enter(&of->f_mutex); 324 ASSERT(of->f_refcnt); 325 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING); 326 of->f_state = SMB_OFILE_STATE_CLOSED; 327 mutex_exit(&of->f_mutex); 328 return; 329 } 330 case SMB_OFILE_STATE_CLOSED: 331 case SMB_OFILE_STATE_CLOSING: 332 break; 333 334 default: 335 ASSERT(0); 336 break; 337 } 338 mutex_exit(&of->f_mutex); 339 } 340 341 /* 342 * smb_ofile_close_all 343 * 344 * 345 */ 346 void 347 smb_ofile_close_all( 348 smb_tree_t *tree) 349 { 350 smb_ofile_t *of; 351 352 ASSERT(tree); 353 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 354 355 smb_llist_enter(&tree->t_ofile_list, RW_READER); 356 of = smb_llist_head(&tree->t_ofile_list); 357 while (of) { 358 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 359 ASSERT(of->f_tree == tree); 360 of = smb_ofile_close_and_next(of); 361 } 362 smb_llist_exit(&tree->t_ofile_list); 363 } 364 365 /* 366 * smb_ofiles_close_by_pid 367 * 368 * 369 */ 370 void 371 smb_ofile_close_all_by_pid( 372 smb_tree_t *tree, 373 uint16_t pid) 374 { 375 smb_ofile_t *of; 376 377 ASSERT(tree); 378 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 379 380 smb_llist_enter(&tree->t_ofile_list, RW_READER); 381 of = smb_llist_head(&tree->t_ofile_list); 382 while (of) { 383 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 384 ASSERT(of->f_tree == tree); 385 if (of->f_opened_by_pid == pid) { 386 of = smb_ofile_close_and_next(of); 387 } else { 388 of = smb_llist_next(&tree->t_ofile_list, of); 389 } 390 } 391 smb_llist_exit(&tree->t_ofile_list); 392 } 393 394 /* 395 * smb_ofile_release 396 * 397 */ 398 void 399 smb_ofile_release( 400 smb_ofile_t *of) 401 { 402 ASSERT(of); 403 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 404 405 mutex_enter(&of->f_mutex); 406 ASSERT(of->f_refcnt); 407 of->f_refcnt--; 408 switch (of->f_state) { 409 case SMB_OFILE_STATE_OPEN: 410 case SMB_OFILE_STATE_CLOSING: 411 break; 412 413 case SMB_OFILE_STATE_CLOSED: 414 if (of->f_refcnt == 0) { 415 mutex_exit(&of->f_mutex); 416 smb_ofile_delete(of); 417 return; 418 } 419 break; 420 421 default: 422 ASSERT(0); 423 break; 424 } 425 mutex_exit(&of->f_mutex); 426 } 427 428 /* 429 * smb_ofile_lookup_by_fid 430 * 431 * Find the open file whose fid matches the one specified in the request. 432 * If we can't find the fid or the shares (trees) don't match, we have a 433 * bad fid. 434 */ 435 smb_ofile_t * 436 smb_ofile_lookup_by_fid( 437 smb_tree_t *tree, 438 uint16_t fid) 439 { 440 smb_llist_t *of_list; 441 smb_ofile_t *of; 442 443 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 444 445 of_list = &tree->t_ofile_list; 446 447 smb_llist_enter(of_list, RW_READER); 448 of = smb_llist_head(of_list); 449 while (of) { 450 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 451 ASSERT(of->f_tree == tree); 452 if (of->f_fid == fid) { 453 mutex_enter(&of->f_mutex); 454 if (of->f_state != SMB_OFILE_STATE_OPEN) { 455 mutex_exit(&of->f_mutex); 456 smb_llist_exit(of_list); 457 return (NULL); 458 } 459 of->f_refcnt++; 460 mutex_exit(&of->f_mutex); 461 break; 462 } 463 of = smb_llist_next(of_list, of); 464 } 465 smb_llist_exit(of_list); 466 return (of); 467 } 468 469 /* 470 * smb_ofile_set_flags 471 * 472 * Return value: 473 * 474 * Current flags value 475 * 476 */ 477 void 478 smb_ofile_set_flags( 479 smb_ofile_t *of, 480 uint32_t flags) 481 { 482 ASSERT(of); 483 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 484 ASSERT(of->f_refcnt); 485 486 mutex_enter(&of->f_mutex); 487 of->f_flags |= flags; 488 mutex_exit(&of->f_mutex); 489 } 490 /* 491 * smb_ofile_seek 492 * 493 * Return value: 494 * 495 * 0 Success 496 * EINVAL Unknown mode 497 * EOVERFLOW offset too big 498 * 499 */ 500 int 501 smb_ofile_seek( 502 smb_ofile_t *of, 503 ushort_t mode, 504 int32_t off, 505 uint32_t *retoff) 506 { 507 u_offset_t newoff = 0; 508 int rc = 0; 509 510 ASSERT(of); 511 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 512 ASSERT(of->f_refcnt); 513 514 mutex_enter(&of->f_mutex); 515 switch (mode) { 516 case SMB_SEEK_SET: 517 if (off < 0) 518 newoff = 0; 519 else 520 newoff = (u_offset_t)off; 521 break; 522 523 case SMB_SEEK_CUR: 524 if (off < 0 && (-off) > of->f_seek_pos) 525 newoff = 0; 526 else 527 newoff = of->f_seek_pos + (u_offset_t)off; 528 break; 529 530 case SMB_SEEK_END: 531 if (off < 0 && (-off) > of->f_node->attr.sa_vattr.va_size) 532 newoff = 0; 533 else 534 newoff = of->f_node->attr.sa_vattr.va_size + 535 (u_offset_t)off; 536 break; 537 538 default: 539 mutex_exit(&of->f_mutex); 540 return (EINVAL); 541 } 542 543 /* 544 * See comments at the beginning of smb_seek.c. 545 * If the offset is greater than UINT_MAX, we will return an error. 546 */ 547 548 if (newoff > UINT_MAX) { 549 rc = EOVERFLOW; 550 } else { 551 of->f_seek_pos = newoff; 552 *retoff = (uint32_t)newoff; 553 } 554 mutex_exit(&of->f_mutex); 555 return (rc); 556 } 557 558 /* 559 * smb_ofile_close_timestamp_update 560 * 561 * The last_wtime is specified in the request received 562 * from the client. If it is neither 0 nor -1, this time 563 * should be used as the file's mtime. It must first be 564 * converted from the server's localtime (as received in 565 * the client's request) to GMT. 566 */ 567 void 568 smb_ofile_close_timestamp_update( 569 smb_ofile_t *of, 570 uint32_t last_wtime) 571 { 572 smb_node_t *node; 573 timestruc_t mtime, atime; 574 unsigned int what = 0; 575 576 mtime.tv_sec = 0; 577 mtime.tv_nsec = 0; 578 579 if (last_wtime != 0 && last_wtime != 0xFFFFFFFF) { 580 mtime.tv_sec = last_wtime + of->f_server->si_gmtoff; 581 what |= SMB_AT_MTIME; 582 } 583 584 /* 585 * NODE_FLAGS_SYNCATIME is set whenever something is 586 * written to a file. 587 */ 588 node = of->f_node; 589 if (node->flags & NODE_FLAGS_SYNCATIME) { 590 what |= SMB_AT_ATIME; 591 (void) microtime(&atime); 592 } 593 594 smb_node_set_time(node, 0, &mtime, &atime, 0, what); 595 } 596 597 /* 598 * smb_ofile_is_open 599 * 600 */ 601 boolean_t 602 smb_ofile_is_open( 603 smb_ofile_t *of) 604 { 605 boolean_t rc = B_FALSE; 606 607 ASSERT(of); 608 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 609 610 mutex_enter(&of->f_mutex); 611 if (of->f_state == SMB_OFILE_STATE_OPEN) { 612 rc = B_TRUE; 613 } 614 mutex_exit(&of->f_mutex); 615 return (rc); 616 } 617 618 /* *************************** Static Functions ***************************** */ 619 620 /* 621 * smb_ofile_close_and_next 622 * 623 * This function closes the file passed in (if appropriate) and returns the 624 * next open file in the list of open files of the tree of the open file passed 625 * in. It requires that the list of open files of the tree be entered in 626 * RW_READER mode before being called. 627 */ 628 static smb_ofile_t * 629 smb_ofile_close_and_next( 630 smb_ofile_t *of) 631 { 632 smb_ofile_t *next_of; 633 smb_tree_t *tree; 634 635 ASSERT(of); 636 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 637 638 mutex_enter(&of->f_mutex); 639 switch (of->f_state) { 640 case SMB_OFILE_STATE_OPEN: 641 /* The file is still open. */ 642 of->f_refcnt++; 643 ASSERT(of->f_refcnt); 644 tree = of->f_tree; 645 mutex_exit(&of->f_mutex); 646 smb_llist_exit(&of->f_tree->t_ofile_list); 647 smb_ofile_close(of, 0); 648 smb_ofile_release(of); 649 smb_llist_enter(&tree->t_ofile_list, RW_READER); 650 next_of = smb_llist_head(&tree->t_ofile_list); 651 break; 652 case SMB_OFILE_STATE_CLOSING: 653 case SMB_OFILE_STATE_CLOSED: 654 /* 655 * The ofile exists but is closed or 656 * in the process being closed. 657 */ 658 mutex_exit(&of->f_mutex); 659 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 660 break; 661 default: 662 ASSERT(0); 663 mutex_exit(&of->f_mutex); 664 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 665 break; 666 } 667 return (next_of); 668 } 669 670 /* 671 * smb_ofile_delete 672 * 673 * 674 */ 675 static void 676 smb_ofile_delete( 677 smb_ofile_t *of) 678 { 679 ASSERT(of); 680 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 681 ASSERT(of->f_refcnt == 0); 682 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); 683 684 /* 685 * Let's remove the ofile from the list of ofiles of the tree. This has 686 * to be done before any resources associated with the ofile are 687 * released. 688 */ 689 smb_llist_enter(&of->f_tree->t_ofile_list, RW_WRITER); 690 smb_llist_remove(&of->f_tree->t_ofile_list, of); 691 smb_llist_exit(&of->f_tree->t_ofile_list); 692 atomic_dec_32(&of->f_session->s_file_cnt); 693 694 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 695 kmem_free(of->f_pipe, sizeof (smb_opipe_t)); 696 of->f_pipe = NULL; 697 } else { 698 ASSERT(of->f_ftype == SMB_FTYPE_DISK); 699 ASSERT(of->f_node != NULL); 700 smb_llist_enter(&of->f_node->n_ofile_list, RW_WRITER); 701 smb_llist_remove(&of->f_node->n_ofile_list, of); 702 smb_llist_exit(&of->f_node->n_ofile_list); 703 smb_node_release(of->f_node); 704 } 705 706 of->f_magic = (uint32_t)~SMB_OFILE_MAGIC; 707 mutex_destroy(&of->f_mutex); 708 crfree(of->f_cr); 709 smb_idpool_free(&of->f_tree->t_fid_pool, of->f_fid); 710 kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of); 711 } 712 713 /* 714 * smb_ofile_access 715 * 716 * This function will check to see if the access requested is granted. 717 * Returns NT status codes. 718 */ 719 uint32_t 720 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access) 721 { 722 723 if ((of == NULL) || (cr == kcred)) 724 return (NT_STATUS_SUCCESS); 725 726 /* 727 * If the request is for something 728 * I don't grant it is an error 729 */ 730 if (~(of->f_granted_access) & access) { 731 if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) && 732 (access & ACCESS_SYSTEM_SECURITY)) { 733 return (NT_STATUS_PRIVILEGE_NOT_HELD); 734 } 735 return (NT_STATUS_ACCESS_DENIED); 736 } 737 738 return (NT_STATUS_SUCCESS); 739 } 740 741 742 /* 743 * smb_ofile_open_check 744 * 745 * check file sharing rules for current open request 746 * against existing open instances of the same file 747 * 748 * Returns NT_STATUS_SHARING_VIOLATION if there is any 749 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 750 */ 751 uint32_t 752 smb_ofile_open_check( 753 smb_ofile_t *of, 754 cred_t *cr, 755 uint32_t desired_access, 756 uint32_t share_access) 757 { 758 smb_node_t *node; 759 760 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 761 762 node = of->f_node; 763 764 mutex_enter(&of->f_mutex); 765 766 if (of->f_state != SMB_OFILE_STATE_OPEN) { 767 mutex_exit(&of->f_mutex); 768 return (NT_STATUS_INVALID_HANDLE); 769 } 770 771 /* 772 * It appears that share modes are not relevant to 773 * directories, but this check will remain as it is not 774 * clear whether it was originally put here for a reason. 775 */ 776 if (node->attr.sa_vattr.va_type == VDIR) { 777 if (SMB_DENY_RW(of->f_share_access) && 778 (node->n_orig_uid != crgetuid(cr))) { 779 mutex_exit(&of->f_mutex); 780 return (NT_STATUS_SHARING_VIOLATION); 781 } 782 783 mutex_exit(&of->f_mutex); 784 return (NT_STATUS_SUCCESS); 785 } 786 787 /* if it's just meta data */ 788 if ((of->f_granted_access & FILE_DATA_ALL) == 0) { 789 mutex_exit(&of->f_mutex); 790 return (NT_STATUS_SUCCESS); 791 } 792 793 /* 794 * Check requested share access against the 795 * open granted (desired) access 796 */ 797 if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) { 798 mutex_exit(&of->f_mutex); 799 return (NT_STATUS_SHARING_VIOLATION); 800 } 801 802 if (SMB_DENY_READ(share_access) && 803 (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) { 804 mutex_exit(&of->f_mutex); 805 return (NT_STATUS_SHARING_VIOLATION); 806 } 807 808 if (SMB_DENY_WRITE(share_access) && 809 (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 810 mutex_exit(&of->f_mutex); 811 return (NT_STATUS_SHARING_VIOLATION); 812 } 813 814 /* check requested desired access against the open share access */ 815 if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) { 816 mutex_exit(&of->f_mutex); 817 return (NT_STATUS_SHARING_VIOLATION); 818 } 819 820 if (SMB_DENY_READ(of->f_share_access) && 821 (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) { 822 mutex_exit(&of->f_mutex); 823 return (NT_STATUS_SHARING_VIOLATION); 824 } 825 826 if (SMB_DENY_WRITE(of->f_share_access) && 827 (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 828 mutex_exit(&of->f_mutex); 829 return (NT_STATUS_SHARING_VIOLATION); 830 } 831 832 mutex_exit(&of->f_mutex); 833 return (NT_STATUS_SUCCESS); 834 } 835 836 /* 837 * smb_ofile_rename_check 838 * 839 * An open file can be renamed if 840 * 841 * 1. isn't opened for data writing or deleting 842 * 843 * 2. Opened with "Deny Delete" share mode 844 * But not opened for data reading or executing 845 * (opened for accessing meta data) 846 */ 847 848 uint32_t 849 smb_ofile_rename_check(smb_ofile_t *of) 850 { 851 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 852 853 mutex_enter(&of->f_mutex); 854 855 if (of->f_state != SMB_OFILE_STATE_OPEN) { 856 mutex_exit(&of->f_mutex); 857 return (NT_STATUS_INVALID_HANDLE); 858 } 859 860 if (of->f_granted_access & 861 (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { 862 mutex_exit(&of->f_mutex); 863 return (NT_STATUS_SHARING_VIOLATION); 864 } 865 866 if ((of->f_share_access & FILE_SHARE_DELETE) == 0) { 867 if (of->f_granted_access & 868 (FILE_READ_DATA | FILE_EXECUTE)) { 869 mutex_exit(&of->f_mutex); 870 return (NT_STATUS_SHARING_VIOLATION); 871 } 872 } 873 874 mutex_exit(&of->f_mutex); 875 return (NT_STATUS_SUCCESS); 876 } 877 878 /* 879 * smb_ofile_delete_check 880 * 881 * An open file can be deleted only if opened for 882 * accessing meta data. Share modes aren't important 883 * in this case. 884 * 885 * NOTE: there is another mechanism for deleting an 886 * open file that NT clients usually use. 887 * That's setting "Delete on close" flag for an open 888 * file. In this way the file will be deleted after 889 * last close. This flag can be set by SmbTrans2SetFileInfo 890 * with FILE_DISPOSITION_INFO information level. 891 * For setting this flag, the file should be opened by 892 * DELETE access in the FID that is passed in the Trans2 893 * request. 894 */ 895 896 uint32_t 897 smb_ofile_delete_check(smb_ofile_t *of) 898 { 899 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 900 901 mutex_enter(&of->f_mutex); 902 903 if (of->f_state != SMB_OFILE_STATE_OPEN) { 904 mutex_exit(&of->f_mutex); 905 return (NT_STATUS_INVALID_HANDLE); 906 } 907 908 if (of->f_granted_access & 909 (FILE_READ_DATA | FILE_WRITE_DATA | 910 FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) { 911 mutex_exit(&of->f_mutex); 912 return (NT_STATUS_SHARING_VIOLATION); 913 } 914 915 mutex_exit(&of->f_mutex); 916 return (NT_STATUS_SUCCESS); 917 } 918 919 cred_t * 920 smb_ofile_getcred(smb_ofile_t *of) 921 { 922 return (of->f_cr); 923 } 924