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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 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_kproto.h> 164 #include <smbsrv/smb_fsops.h> 165 166 static boolean_t smb_ofile_is_open_locked(smb_ofile_t *); 167 static smb_ofile_t *smb_ofile_close_and_next(smb_ofile_t *); 168 static int smb_ofile_netinfo_encode(smb_ofile_t *, uint8_t *, size_t, 169 uint32_t *); 170 static int smb_ofile_netinfo_init(smb_ofile_t *, smb_netfileinfo_t *); 171 static void smb_ofile_netinfo_fini(smb_netfileinfo_t *); 172 173 /* 174 * smb_ofile_open 175 */ 176 smb_ofile_t * 177 smb_ofile_open( 178 smb_request_t *sr, 179 smb_node_t *node, 180 struct open_param *op, 181 uint16_t ftype, 182 uint32_t uniqid, 183 smb_error_t *err) 184 { 185 smb_tree_t *tree = sr->tid_tree; 186 smb_ofile_t *of; 187 uint16_t fid; 188 smb_attr_t attr; 189 int rc; 190 enum errstates { EMPTY, FIDALLOC, CRHELD, MUTEXINIT }; 191 enum errstates state = EMPTY; 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 state = FIDALLOC; 200 201 of = kmem_cache_alloc(smb_cache_ofile, KM_SLEEP); 202 bzero(of, sizeof (smb_ofile_t)); 203 of->f_magic = SMB_OFILE_MAGIC; 204 of->f_refcnt = 1; 205 of->f_fid = fid; 206 of->f_uniqid = uniqid; 207 of->f_opened_by_pid = sr->smb_pid; 208 of->f_granted_access = op->desired_access; 209 of->f_share_access = op->share_access; 210 of->f_create_options = op->create_options; 211 of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ? 212 smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred; 213 crhold(of->f_cr); 214 state = CRHELD; 215 of->f_ftype = ftype; 216 of->f_server = tree->t_server; 217 of->f_session = tree->t_session; 218 /* 219 * grab a ref for of->f_user 220 * released in smb_ofile_delete() 221 */ 222 smb_user_hold_internal(sr->uid_user); 223 of->f_user = sr->uid_user; 224 of->f_tree = tree; 225 of->f_node = node; 226 227 mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL); 228 state = MUTEXINIT; 229 of->f_state = SMB_OFILE_STATE_OPEN; 230 231 if (ftype == SMB_FTYPE_MESG_PIPE) { 232 /* See smb_opipe_open. */ 233 of->f_pipe = op->pipe; 234 smb_server_inc_pipes(of->f_server); 235 } else { 236 ASSERT(ftype == SMB_FTYPE_DISK); /* Regular file, not a pipe */ 237 ASSERT(node); 238 239 if (of->f_granted_access == FILE_EXECUTE) 240 of->f_flags |= SMB_OFLAGS_EXECONLY; 241 242 bzero(&attr, sizeof (smb_attr_t)); 243 attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR; 244 rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr); 245 if (rc != 0) { 246 err->status = NT_STATUS_INTERNAL_ERROR; 247 err->errcls = ERRDOS; 248 err->errcode = ERROR_INTERNAL_ERROR; 249 goto errout; 250 } 251 if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) { 252 /* 253 * Add this bit for the file's owner even if it's not 254 * specified in the request (Windows behavior). 255 */ 256 of->f_granted_access |= FILE_READ_ATTRIBUTES; 257 } 258 259 if (smb_node_is_file(node)) { 260 of->f_mode = 261 smb_fsop_amask_to_omode(of->f_granted_access); 262 if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) { 263 err->status = NT_STATUS_ACCESS_DENIED; 264 err->errcls = ERRDOS; 265 err->errcode = ERROR_ACCESS_DENIED; 266 goto errout; 267 } 268 } 269 270 if (tree->t_flags & SMB_TREE_READONLY) 271 of->f_flags |= SMB_OFLAGS_READONLY; 272 273 /* 274 * Note that if we created_readonly, that 275 * will _not_ yet show in attr.sa_dosattr 276 * so creating a readonly file gives the 277 * caller a writable handle as it should. 278 */ 279 if (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) 280 of->f_flags |= SMB_OFLAGS_READONLY; 281 282 smb_node_inc_open_ofiles(node); 283 smb_node_add_ofile(node, of); 284 smb_node_ref(node); 285 smb_server_inc_files(of->f_server); 286 } 287 smb_llist_enter(&tree->t_ofile_list, RW_WRITER); 288 smb_llist_insert_tail(&tree->t_ofile_list, of); 289 smb_llist_exit(&tree->t_ofile_list); 290 atomic_inc_32(&tree->t_open_files); 291 atomic_inc_32(&of->f_session->s_file_cnt); 292 return (of); 293 294 errout: 295 switch (state) { 296 case MUTEXINIT: 297 mutex_destroy(&of->f_mutex); 298 smb_user_release(of->f_user); 299 /*FALLTHROUGH*/ 300 case CRHELD: 301 crfree(of->f_cr); 302 of->f_magic = 0; 303 kmem_cache_free(smb_cache_ofile, of); 304 /*FALLTHROUGH*/ 305 case FIDALLOC: 306 smb_idpool_free(&tree->t_fid_pool, fid); 307 /*FALLTHROUGH*/ 308 case EMPTY: 309 break; 310 } 311 return (NULL); 312 } 313 314 /* 315 * smb_ofile_close 316 */ 317 void 318 smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec) 319 { 320 timestruc_t now; 321 uint32_t flags = 0; 322 323 SMB_OFILE_VALID(of); 324 325 mutex_enter(&of->f_mutex); 326 ASSERT(of->f_refcnt); 327 if (of->f_state != SMB_OFILE_STATE_OPEN) { 328 mutex_exit(&of->f_mutex); 329 return; 330 } 331 of->f_state = SMB_OFILE_STATE_CLOSING; 332 mutex_exit(&of->f_mutex); 333 334 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 335 smb_opipe_close(of); 336 smb_server_dec_pipes(of->f_server); 337 } else { 338 smb_attr_t *pa = &of->f_pending_attr; 339 340 /* 341 * In here we make changes to of->f_pending_attr 342 * while not holding of->f_mutex. This is OK 343 * because we've changed f_state to CLOSING, 344 * so no more threads will take this path. 345 */ 346 if (mtime_sec != 0) { 347 pa->sa_vattr.va_mtime.tv_sec = mtime_sec; 348 pa->sa_mask |= SMB_AT_MTIME; 349 } 350 351 /* 352 * If we have ever modified data via this handle 353 * (write or truncate) and if the mtime was not 354 * set via this handle, update the mtime again 355 * during the close. Windows expects this. 356 * [ MS-FSA 2.1.5.4 "Update Timestamps" ] 357 */ 358 if (of->f_written && 359 (pa->sa_mask & SMB_AT_MTIME) == 0) { 360 pa->sa_mask |= SMB_AT_MTIME; 361 gethrestime(&now); 362 pa->sa_vattr.va_mtime = now; 363 } 364 365 if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) { 366 if (smb_tree_has_feature(of->f_tree, 367 SMB_TREE_CATIA)) { 368 flags |= SMB_CATIA; 369 } 370 (void) smb_node_set_delete_on_close(of->f_node, 371 of->f_cr, flags); 372 } 373 smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid); 374 smb_node_destroy_lock_by_ofile(of->f_node, of); 375 376 if (smb_node_is_file(of->f_node)) { 377 (void) smb_fsop_close(of->f_node, of->f_mode, 378 of->f_cr); 379 smb_oplock_release(of->f_node, of); 380 } 381 if (smb_node_dec_open_ofiles(of->f_node) == 0) { 382 /* 383 * Last close. The f_pending_attr has 384 * only times (atime,ctime,mtime) so 385 * we can borrow it to commit the 386 * n_pending_dosattr from the node. 387 */ 388 pa->sa_dosattr = 389 of->f_node->n_pending_dosattr; 390 if (pa->sa_dosattr != 0) 391 pa->sa_mask |= SMB_AT_DOSATTR; 392 /* Let's leave this zero when not in use. */ 393 of->f_node->n_allocsz = 0; 394 } 395 if (pa->sa_mask != 0) { 396 /* 397 * Commit any pending attributes from 398 * the ofile we're closing. Note that 399 * we pass NULL as the ofile to setattr 400 * so it will write to the file system 401 * and not keep anything on the ofile. 402 * This clears n_pending_dosattr if 403 * there are no opens, otherwise the 404 * dosattr will be pending again. 405 */ 406 (void) smb_node_setattr(NULL, of->f_node, 407 of->f_cr, NULL, pa); 408 } 409 410 /* 411 * Cancel any notify change requests that 412 * may be using this open instance. 413 */ 414 if (of->f_node->n_fcn.fcn_count) 415 smb_notify_file_closed(of); 416 417 smb_server_dec_files(of->f_server); 418 } 419 atomic_dec_32(&of->f_tree->t_open_files); 420 421 mutex_enter(&of->f_mutex); 422 ASSERT(of->f_refcnt); 423 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING); 424 of->f_state = SMB_OFILE_STATE_CLOSED; 425 mutex_exit(&of->f_mutex); 426 } 427 428 /* 429 * smb_ofile_close_all 430 * 431 * 432 */ 433 void 434 smb_ofile_close_all( 435 smb_tree_t *tree) 436 { 437 smb_ofile_t *of; 438 439 ASSERT(tree); 440 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 441 442 smb_llist_enter(&tree->t_ofile_list, RW_READER); 443 of = smb_llist_head(&tree->t_ofile_list); 444 while (of) { 445 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 446 ASSERT(of->f_tree == tree); 447 of = smb_ofile_close_and_next(of); 448 } 449 smb_llist_exit(&tree->t_ofile_list); 450 } 451 452 /* 453 * smb_ofiles_close_by_pid 454 * 455 * 456 */ 457 void 458 smb_ofile_close_all_by_pid( 459 smb_tree_t *tree, 460 uint16_t pid) 461 { 462 smb_ofile_t *of; 463 464 ASSERT(tree); 465 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 466 467 smb_llist_enter(&tree->t_ofile_list, RW_READER); 468 of = smb_llist_head(&tree->t_ofile_list); 469 while (of) { 470 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 471 ASSERT(of->f_tree == tree); 472 if (of->f_opened_by_pid == pid) { 473 of = smb_ofile_close_and_next(of); 474 } else { 475 of = smb_llist_next(&tree->t_ofile_list, of); 476 } 477 } 478 smb_llist_exit(&tree->t_ofile_list); 479 } 480 481 /* 482 * If the enumeration request is for ofile data, handle it here. 483 * Otherwise, return. 484 * 485 * This function should be called with a hold on the ofile. 486 */ 487 int 488 smb_ofile_enum(smb_ofile_t *of, smb_svcenum_t *svcenum) 489 { 490 uint8_t *pb; 491 uint_t nbytes; 492 int rc; 493 494 ASSERT(of); 495 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 496 ASSERT(of->f_refcnt); 497 498 if (svcenum->se_type != SMB_SVCENUM_TYPE_FILE) 499 return (0); 500 501 if (svcenum->se_nskip > 0) { 502 svcenum->se_nskip--; 503 return (0); 504 } 505 506 if (svcenum->se_nitems >= svcenum->se_nlimit) { 507 svcenum->se_nitems = svcenum->se_nlimit; 508 return (0); 509 } 510 511 pb = &svcenum->se_buf[svcenum->se_bused]; 512 513 rc = smb_ofile_netinfo_encode(of, pb, svcenum->se_bavail, 514 &nbytes); 515 if (rc == 0) { 516 svcenum->se_bavail -= nbytes; 517 svcenum->se_bused += nbytes; 518 svcenum->se_nitems++; 519 } 520 521 return (rc); 522 } 523 524 /* 525 * Take a reference on an open file. 526 */ 527 boolean_t 528 smb_ofile_hold(smb_ofile_t *of) 529 { 530 ASSERT(of); 531 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 532 533 mutex_enter(&of->f_mutex); 534 535 if (of->f_state != SMB_OFILE_STATE_OPEN) { 536 mutex_exit(&of->f_mutex); 537 return (B_FALSE); 538 } 539 of->f_refcnt++; 540 541 mutex_exit(&of->f_mutex); 542 return (B_TRUE); 543 } 544 545 /* 546 * Release a reference on a file. If the reference count falls to 547 * zero and the file has been closed, post the object for deletion. 548 * Object deletion is deferred to avoid modifying a list while an 549 * iteration may be in progress. 550 */ 551 void 552 smb_ofile_release(smb_ofile_t *of) 553 { 554 SMB_OFILE_VALID(of); 555 556 mutex_enter(&of->f_mutex); 557 ASSERT(of->f_refcnt); 558 of->f_refcnt--; 559 switch (of->f_state) { 560 case SMB_OFILE_STATE_OPEN: 561 case SMB_OFILE_STATE_CLOSING: 562 break; 563 564 case SMB_OFILE_STATE_CLOSED: 565 if (of->f_refcnt == 0) 566 smb_tree_post_ofile(of->f_tree, of); 567 break; 568 569 default: 570 ASSERT(0); 571 break; 572 } 573 mutex_exit(&of->f_mutex); 574 } 575 576 /* 577 * smb_ofile_request_complete 578 * 579 * During oplock acquisition, all other oplock requests on the node 580 * are blocked until the acquire request completes and the response 581 * is on the wire. 582 * Call smb_oplock_broadcast to notify the node that the request 583 * has completed. 584 * 585 * THIS MECHANISM RELIES ON THE FACT THAT THE OFILE IS NOT REMOVED 586 * FROM THE SR UNTIL REQUEST COMPLETION (when the sr is destroyed) 587 */ 588 void 589 smb_ofile_request_complete(smb_ofile_t *of) 590 { 591 SMB_OFILE_VALID(of); 592 593 switch (of->f_ftype) { 594 case SMB_FTYPE_DISK: 595 ASSERT(of->f_node); 596 smb_oplock_broadcast(of->f_node); 597 break; 598 case SMB_FTYPE_MESG_PIPE: 599 break; 600 default: 601 break; 602 } 603 } 604 605 /* 606 * smb_ofile_lookup_by_fid 607 * 608 * Find the open file whose fid matches the one specified in the request. 609 * If we can't find the fid or the shares (trees) don't match, we have a 610 * bad fid. 611 */ 612 smb_ofile_t * 613 smb_ofile_lookup_by_fid( 614 smb_request_t *sr, 615 uint16_t fid) 616 { 617 smb_tree_t *tree = sr->tid_tree; 618 smb_llist_t *of_list; 619 smb_ofile_t *of; 620 621 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 622 623 of_list = &tree->t_ofile_list; 624 625 smb_llist_enter(of_list, RW_READER); 626 of = smb_llist_head(of_list); 627 while (of) { 628 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 629 ASSERT(of->f_tree == tree); 630 if (of->f_fid == fid) 631 break; 632 of = smb_llist_next(of_list, of); 633 } 634 if (of == NULL) 635 goto out; 636 637 /* 638 * Only allow use of a given FID with the same UID that 639 * was used to open it. MS-CIFS 3.3.5.14 640 */ 641 if (of->f_user != sr->uid_user) { 642 of = NULL; 643 goto out; 644 } 645 646 mutex_enter(&of->f_mutex); 647 if (of->f_state != SMB_OFILE_STATE_OPEN) { 648 mutex_exit(&of->f_mutex); 649 of = NULL; 650 goto out; 651 } 652 of->f_refcnt++; 653 mutex_exit(&of->f_mutex); 654 655 out: 656 smb_llist_exit(of_list); 657 return (of); 658 } 659 660 /* 661 * smb_ofile_lookup_by_uniqid 662 * 663 * Find the open file whose uniqid matches the one specified in the request. 664 */ 665 smb_ofile_t * 666 smb_ofile_lookup_by_uniqid(smb_tree_t *tree, uint32_t uniqid) 667 { 668 smb_llist_t *of_list; 669 smb_ofile_t *of; 670 671 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 672 673 of_list = &tree->t_ofile_list; 674 smb_llist_enter(of_list, RW_READER); 675 of = smb_llist_head(of_list); 676 677 while (of) { 678 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 679 ASSERT(of->f_tree == tree); 680 681 if (of->f_uniqid == uniqid) { 682 if (smb_ofile_hold(of)) { 683 smb_llist_exit(of_list); 684 return (of); 685 } 686 } 687 688 of = smb_llist_next(of_list, of); 689 } 690 691 smb_llist_exit(of_list); 692 return (NULL); 693 } 694 695 /* 696 * Disallow NetFileClose on certain ofiles to avoid side-effects. 697 * Closing a tree root is not allowed: use NetSessionDel or NetShareDel. 698 * Closing SRVSVC connections is not allowed because this NetFileClose 699 * request may depend on this ofile. 700 */ 701 boolean_t 702 smb_ofile_disallow_fclose(smb_ofile_t *of) 703 { 704 ASSERT(of); 705 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 706 ASSERT(of->f_refcnt); 707 708 switch (of->f_ftype) { 709 case SMB_FTYPE_DISK: 710 ASSERT(of->f_tree); 711 return (of->f_node == of->f_tree->t_snode); 712 713 case SMB_FTYPE_MESG_PIPE: 714 ASSERT(of->f_pipe); 715 if (smb_strcasecmp(of->f_pipe->p_name, "SRVSVC", 0) == 0) 716 return (B_TRUE); 717 break; 718 default: 719 break; 720 } 721 722 return (B_FALSE); 723 } 724 725 /* 726 * smb_ofile_set_flags 727 * 728 * Return value: 729 * 730 * Current flags value 731 * 732 */ 733 void 734 smb_ofile_set_flags( 735 smb_ofile_t *of, 736 uint32_t flags) 737 { 738 ASSERT(of); 739 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 740 ASSERT(of->f_refcnt); 741 742 mutex_enter(&of->f_mutex); 743 of->f_flags |= flags; 744 mutex_exit(&of->f_mutex); 745 } 746 747 /* 748 * smb_ofile_seek 749 * 750 * Return value: 751 * 752 * 0 Success 753 * EINVAL Unknown mode 754 * EOVERFLOW offset too big 755 * 756 */ 757 int 758 smb_ofile_seek( 759 smb_ofile_t *of, 760 ushort_t mode, 761 int32_t off, 762 uint32_t *retoff) 763 { 764 u_offset_t newoff = 0; 765 int rc = 0; 766 smb_attr_t attr; 767 768 ASSERT(of); 769 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 770 ASSERT(of->f_refcnt); 771 772 mutex_enter(&of->f_mutex); 773 switch (mode) { 774 case SMB_SEEK_SET: 775 if (off < 0) 776 newoff = 0; 777 else 778 newoff = (u_offset_t)off; 779 break; 780 781 case SMB_SEEK_CUR: 782 if (off < 0 && (-off) > of->f_seek_pos) 783 newoff = 0; 784 else 785 newoff = of->f_seek_pos + (u_offset_t)off; 786 break; 787 788 case SMB_SEEK_END: 789 bzero(&attr, sizeof (smb_attr_t)); 790 attr.sa_mask |= SMB_AT_SIZE; 791 rc = smb_fsop_getattr(NULL, zone_kcred(), of->f_node, &attr); 792 if (rc != 0) { 793 mutex_exit(&of->f_mutex); 794 return (rc); 795 } 796 if (off < 0 && (-off) > attr.sa_vattr.va_size) 797 newoff = 0; 798 else 799 newoff = attr.sa_vattr.va_size + (u_offset_t)off; 800 break; 801 802 default: 803 mutex_exit(&of->f_mutex); 804 return (EINVAL); 805 } 806 807 /* 808 * See comments at the beginning of smb_seek.c. 809 * If the offset is greater than UINT_MAX, we will return an error. 810 */ 811 812 if (newoff > UINT_MAX) { 813 rc = EOVERFLOW; 814 } else { 815 of->f_seek_pos = newoff; 816 *retoff = (uint32_t)newoff; 817 } 818 mutex_exit(&of->f_mutex); 819 return (rc); 820 } 821 822 /* 823 * smb_ofile_is_open 824 */ 825 boolean_t 826 smb_ofile_is_open(smb_ofile_t *of) 827 { 828 boolean_t rc; 829 830 SMB_OFILE_VALID(of); 831 832 mutex_enter(&of->f_mutex); 833 rc = smb_ofile_is_open_locked(of); 834 mutex_exit(&of->f_mutex); 835 return (rc); 836 } 837 838 /* *************************** Static Functions ***************************** */ 839 840 /* 841 * Determine whether or not an ofile is open. 842 * This function must be called with the mutex held. 843 */ 844 static boolean_t 845 smb_ofile_is_open_locked(smb_ofile_t *of) 846 { 847 switch (of->f_state) { 848 case SMB_OFILE_STATE_OPEN: 849 return (B_TRUE); 850 851 case SMB_OFILE_STATE_CLOSING: 852 case SMB_OFILE_STATE_CLOSED: 853 return (B_FALSE); 854 855 default: 856 ASSERT(0); 857 return (B_FALSE); 858 } 859 } 860 861 /* 862 * This function closes the file passed in (if appropriate) and returns the 863 * next open file in the list of open files of the tree of the open file passed 864 * in. It requires that the list of open files of the tree be entered in 865 * RW_READER mode before being called. 866 */ 867 static smb_ofile_t * 868 smb_ofile_close_and_next(smb_ofile_t *of) 869 { 870 smb_ofile_t *next_of; 871 smb_tree_t *tree; 872 873 ASSERT(of); 874 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 875 876 mutex_enter(&of->f_mutex); 877 switch (of->f_state) { 878 case SMB_OFILE_STATE_OPEN: 879 /* The file is still open. */ 880 of->f_refcnt++; 881 ASSERT(of->f_refcnt); 882 tree = of->f_tree; 883 mutex_exit(&of->f_mutex); 884 smb_llist_exit(&of->f_tree->t_ofile_list); 885 smb_ofile_close(of, 0); 886 smb_ofile_release(of); 887 smb_llist_enter(&tree->t_ofile_list, RW_READER); 888 next_of = smb_llist_head(&tree->t_ofile_list); 889 break; 890 case SMB_OFILE_STATE_CLOSING: 891 case SMB_OFILE_STATE_CLOSED: 892 /* 893 * The ofile exists but is closed or 894 * in the process being closed. 895 */ 896 mutex_exit(&of->f_mutex); 897 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 898 break; 899 default: 900 ASSERT(0); 901 mutex_exit(&of->f_mutex); 902 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 903 break; 904 } 905 return (next_of); 906 } 907 908 /* 909 * Delete an ofile. 910 * 911 * Remove the ofile from the tree list before freeing resources 912 * associated with the ofile. 913 */ 914 void 915 smb_ofile_delete(void *arg) 916 { 917 smb_tree_t *tree; 918 smb_ofile_t *of = (smb_ofile_t *)arg; 919 920 SMB_OFILE_VALID(of); 921 ASSERT(of->f_refcnt == 0); 922 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); 923 ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of)); 924 925 tree = of->f_tree; 926 smb_llist_enter(&tree->t_ofile_list, RW_WRITER); 927 smb_llist_remove(&tree->t_ofile_list, of); 928 smb_idpool_free(&tree->t_fid_pool, of->f_fid); 929 atomic_dec_32(&tree->t_session->s_file_cnt); 930 smb_llist_exit(&tree->t_ofile_list); 931 932 mutex_enter(&of->f_mutex); 933 mutex_exit(&of->f_mutex); 934 935 if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 936 smb_opipe_dealloc(of->f_pipe); 937 of->f_pipe = NULL; 938 } else { 939 ASSERT(of->f_ftype == SMB_FTYPE_DISK); 940 ASSERT(of->f_node != NULL); 941 smb_node_rem_ofile(of->f_node, of); 942 smb_node_release(of->f_node); 943 } 944 945 of->f_magic = (uint32_t)~SMB_OFILE_MAGIC; 946 mutex_destroy(&of->f_mutex); 947 crfree(of->f_cr); 948 smb_user_release(of->f_user); 949 kmem_cache_free(smb_cache_ofile, of); 950 } 951 952 /* 953 * smb_ofile_access 954 * 955 * This function will check to see if the access requested is granted. 956 * Returns NT status codes. 957 */ 958 uint32_t 959 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access) 960 { 961 962 if ((of == NULL) || (cr == zone_kcred())) 963 return (NT_STATUS_SUCCESS); 964 965 /* 966 * If the request is for something 967 * I don't grant it is an error 968 */ 969 if (~(of->f_granted_access) & access) { 970 if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) && 971 (access & ACCESS_SYSTEM_SECURITY)) { 972 return (NT_STATUS_PRIVILEGE_NOT_HELD); 973 } 974 return (NT_STATUS_ACCESS_DENIED); 975 } 976 977 return (NT_STATUS_SUCCESS); 978 } 979 980 /* 981 * smb_ofile_share_check 982 * 983 * Check if ofile was opened with share access NONE (0). 984 * Returns: B_TRUE - share access non-zero 985 * B_FALSE - share access NONE 986 */ 987 boolean_t 988 smb_ofile_share_check(smb_ofile_t *of) 989 { 990 return (!SMB_DENY_ALL(of->f_share_access)); 991 } 992 993 /* 994 * check file sharing rules for current open request 995 * against existing open instances of the same file 996 * 997 * Returns NT_STATUS_SHARING_VIOLATION if there is any 998 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 999 */ 1000 uint32_t 1001 smb_ofile_open_check(smb_ofile_t *of, uint32_t desired_access, 1002 uint32_t share_access) 1003 { 1004 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 1005 1006 mutex_enter(&of->f_mutex); 1007 1008 if (of->f_state != SMB_OFILE_STATE_OPEN) { 1009 mutex_exit(&of->f_mutex); 1010 return (NT_STATUS_INVALID_HANDLE); 1011 } 1012 1013 /* if it's just meta data */ 1014 if ((of->f_granted_access & FILE_DATA_ALL) == 0) { 1015 mutex_exit(&of->f_mutex); 1016 return (NT_STATUS_SUCCESS); 1017 } 1018 1019 /* 1020 * Check requested share access against the 1021 * open granted (desired) access 1022 */ 1023 if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) { 1024 mutex_exit(&of->f_mutex); 1025 return (NT_STATUS_SHARING_VIOLATION); 1026 } 1027 1028 if (SMB_DENY_READ(share_access) && 1029 (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) { 1030 mutex_exit(&of->f_mutex); 1031 return (NT_STATUS_SHARING_VIOLATION); 1032 } 1033 1034 if (SMB_DENY_WRITE(share_access) && 1035 (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 1036 mutex_exit(&of->f_mutex); 1037 return (NT_STATUS_SHARING_VIOLATION); 1038 } 1039 1040 /* check requested desired access against the open share access */ 1041 if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) { 1042 mutex_exit(&of->f_mutex); 1043 return (NT_STATUS_SHARING_VIOLATION); 1044 } 1045 1046 if (SMB_DENY_READ(of->f_share_access) && 1047 (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) { 1048 mutex_exit(&of->f_mutex); 1049 return (NT_STATUS_SHARING_VIOLATION); 1050 } 1051 1052 if (SMB_DENY_WRITE(of->f_share_access) && 1053 (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 1054 mutex_exit(&of->f_mutex); 1055 return (NT_STATUS_SHARING_VIOLATION); 1056 } 1057 1058 mutex_exit(&of->f_mutex); 1059 return (NT_STATUS_SUCCESS); 1060 } 1061 1062 /* 1063 * smb_ofile_rename_check 1064 * 1065 * An open file can be renamed if 1066 * 1067 * 1. isn't opened for data writing or deleting 1068 * 1069 * 2. Opened with "Deny Delete" share mode 1070 * But not opened for data reading or executing 1071 * (opened for accessing meta data) 1072 */ 1073 1074 uint32_t 1075 smb_ofile_rename_check(smb_ofile_t *of) 1076 { 1077 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 1078 1079 mutex_enter(&of->f_mutex); 1080 1081 if (of->f_state != SMB_OFILE_STATE_OPEN) { 1082 mutex_exit(&of->f_mutex); 1083 return (NT_STATUS_INVALID_HANDLE); 1084 } 1085 1086 if (of->f_granted_access & 1087 (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { 1088 mutex_exit(&of->f_mutex); 1089 return (NT_STATUS_SHARING_VIOLATION); 1090 } 1091 1092 if ((of->f_share_access & FILE_SHARE_DELETE) == 0) { 1093 if (of->f_granted_access & 1094 (FILE_READ_DATA | FILE_EXECUTE)) { 1095 mutex_exit(&of->f_mutex); 1096 return (NT_STATUS_SHARING_VIOLATION); 1097 } 1098 } 1099 1100 mutex_exit(&of->f_mutex); 1101 return (NT_STATUS_SUCCESS); 1102 } 1103 1104 /* 1105 * smb_ofile_delete_check 1106 * 1107 * An open file can be deleted only if opened for 1108 * accessing meta data. Share modes aren't important 1109 * in this case. 1110 * 1111 * NOTE: there is another mechanism for deleting an 1112 * open file that NT clients usually use. 1113 * That's setting "Delete on close" flag for an open 1114 * file. In this way the file will be deleted after 1115 * last close. This flag can be set by SmbTrans2SetFileInfo 1116 * with FILE_DISPOSITION_INFO information level. 1117 * For setting this flag, the file should be opened by 1118 * DELETE access in the FID that is passed in the Trans2 1119 * request. 1120 */ 1121 1122 uint32_t 1123 smb_ofile_delete_check(smb_ofile_t *of) 1124 { 1125 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 1126 1127 mutex_enter(&of->f_mutex); 1128 1129 if (of->f_state != SMB_OFILE_STATE_OPEN) { 1130 mutex_exit(&of->f_mutex); 1131 return (NT_STATUS_INVALID_HANDLE); 1132 } 1133 1134 if (of->f_granted_access & 1135 (FILE_READ_DATA | FILE_WRITE_DATA | 1136 FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) { 1137 mutex_exit(&of->f_mutex); 1138 return (NT_STATUS_SHARING_VIOLATION); 1139 } 1140 1141 mutex_exit(&of->f_mutex); 1142 return (NT_STATUS_SUCCESS); 1143 } 1144 1145 cred_t * 1146 smb_ofile_getcred(smb_ofile_t *of) 1147 { 1148 return (of->f_cr); 1149 } 1150 1151 /* 1152 * smb_ofile_set_delete_on_close 1153 * 1154 * Set the DeleteOnClose flag on the smb file. When the file is closed, 1155 * the flag will be transferred to the smb node, which will commit the 1156 * delete operation and inhibit subsequent open requests. 1157 * 1158 * When DeleteOnClose is set on an smb_node, the common open code will 1159 * reject subsequent open requests for the file. Observation of Windows 1160 * 2000 indicates that subsequent opens should be allowed (assuming 1161 * there would be no sharing violation) until the file is closed using 1162 * the fid on which the DeleteOnClose was requested. 1163 */ 1164 void 1165 smb_ofile_set_delete_on_close(smb_ofile_t *of) 1166 { 1167 mutex_enter(&of->f_mutex); 1168 of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE; 1169 mutex_exit(&of->f_mutex); 1170 } 1171 1172 /* 1173 * Encode open file information into a buffer; needed in user space to 1174 * support RPC requests. 1175 */ 1176 static int 1177 smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen, 1178 uint32_t *nbytes) 1179 { 1180 smb_netfileinfo_t fi; 1181 int rc; 1182 1183 rc = smb_ofile_netinfo_init(of, &fi); 1184 if (rc == 0) { 1185 rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes); 1186 smb_ofile_netinfo_fini(&fi); 1187 } 1188 1189 return (rc); 1190 } 1191 1192 static int 1193 smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi) 1194 { 1195 smb_user_t *user; 1196 smb_tree_t *tree; 1197 smb_node_t *node; 1198 char *path; 1199 char *buf; 1200 int rc; 1201 1202 ASSERT(of); 1203 user = of->f_user; 1204 tree = of->f_tree; 1205 ASSERT(user); 1206 ASSERT(tree); 1207 1208 buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 1209 1210 switch (of->f_ftype) { 1211 case SMB_FTYPE_DISK: 1212 node = of->f_node; 1213 ASSERT(node); 1214 1215 fi->fi_permissions = of->f_granted_access; 1216 fi->fi_numlocks = smb_lock_get_lock_count(node, of); 1217 1218 path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 1219 1220 if (node != tree->t_snode) { 1221 rc = smb_node_getshrpath(node, tree, path, MAXPATHLEN); 1222 if (rc != 0) 1223 (void) strlcpy(path, node->od_name, MAXPATHLEN); 1224 } 1225 1226 (void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename, 1227 path); 1228 kmem_free(path, MAXPATHLEN); 1229 break; 1230 1231 case SMB_FTYPE_MESG_PIPE: 1232 ASSERT(of->f_pipe); 1233 1234 fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA | 1235 FILE_EXECUTE; 1236 fi->fi_numlocks = 0; 1237 (void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s", 1238 of->f_pipe->p_name); 1239 break; 1240 1241 default: 1242 kmem_free(buf, MAXPATHLEN); 1243 return (-1); 1244 } 1245 1246 fi->fi_fid = of->f_fid; 1247 fi->fi_uniqid = of->f_uniqid; 1248 fi->fi_pathlen = strlen(buf) + 1; 1249 fi->fi_path = smb_mem_strdup(buf); 1250 kmem_free(buf, MAXPATHLEN); 1251 1252 fi->fi_namelen = user->u_domain_len + user->u_name_len + 2; 1253 fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP); 1254 (void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s", 1255 user->u_domain, user->u_name); 1256 return (0); 1257 } 1258 1259 static void 1260 smb_ofile_netinfo_fini(smb_netfileinfo_t *fi) 1261 { 1262 if (fi == NULL) 1263 return; 1264 1265 if (fi->fi_path) 1266 smb_mem_free(fi->fi_path); 1267 if (fi->fi_username) 1268 kmem_free(fi->fi_username, fi->fi_namelen); 1269 1270 bzero(fi, sizeof (smb_netfileinfo_t)); 1271 } 1272 1273 /* 1274 * A query of user and group quotas may span multiple requests. 1275 * f_quota_resume is used to determine where the query should 1276 * be resumed, in a subsequent request. f_quota_resume contains 1277 * the SID of the last quota entry returned to the client. 1278 */ 1279 void 1280 smb_ofile_set_quota_resume(smb_ofile_t *ofile, char *resume) 1281 { 1282 ASSERT(ofile); 1283 mutex_enter(&ofile->f_mutex); 1284 if (resume == NULL) 1285 bzero(ofile->f_quota_resume, SMB_SID_STRSZ); 1286 else 1287 (void) strlcpy(ofile->f_quota_resume, resume, SMB_SID_STRSZ); 1288 mutex_exit(&ofile->f_mutex); 1289 } 1290 1291 void 1292 smb_ofile_get_quota_resume(smb_ofile_t *ofile, char *buf, int bufsize) 1293 { 1294 ASSERT(ofile); 1295 mutex_enter(&ofile->f_mutex); 1296 (void) strlcpy(buf, ofile->f_quota_resume, bufsize); 1297 mutex_exit(&ofile->f_mutex); 1298 } 1299