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