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