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 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <sys/sid.h>
  27 #include <sys/nbmlock.h>
  28 #include <smbsrv/smb_fsops.h>
  29 #include <smbsrv/smb_kproto.h>
  30 #include <acl/acl_common.h>
  31 #include <sys/fcntl.h>
  32 #include <sys/flock.h>
  33 #include <fs/fs_subr.h>
  34 
  35 extern caller_context_t smb_ct;
  36 
  37 static int smb_fsop_create_stream(smb_request_t *, cred_t *, smb_node_t *,
  38     char *, char *, int, smb_attr_t *, smb_node_t **);
  39 
  40 static int smb_fsop_create_file(smb_request_t *, cred_t *, smb_node_t *,
  41     char *, int, smb_attr_t *, smb_node_t **);
  42 
  43 #ifdef  _KERNEL
  44 static int smb_fsop_create_with_sd(smb_request_t *, cred_t *, smb_node_t *,
  45     char *, smb_attr_t *, smb_node_t **, smb_fssd_t *);
  46 static int smb_fsop_sdinherit(smb_request_t *, smb_node_t *, smb_fssd_t *);
  47 #endif  /* _KERNEL */
  48 
  49 /*
  50  * The smb_fsop_* functions have knowledge of CIFS semantics.
  51  *
  52  * The smb_vop_* functions have minimal knowledge of CIFS semantics and
  53  * serve as an interface to the VFS layer.
  54  *
  55  * Hence, smb_request_t and smb_node_t structures should not be passed
  56  * from the smb_fsop_* layer to the smb_vop_* layer.
  57  *
  58  * In general, CIFS service code should only ever call smb_fsop_*
 
 
 116 {
 117         smb_vop_close(node->vp, mode, cred);
 118 }
 119 
 120 #ifdef  _KERNEL
 121 static int
 122 smb_fsop_create_with_sd(smb_request_t *sr, cred_t *cr,
 123     smb_node_t *dnode, char *name,
 124     smb_attr_t *attr, smb_node_t **ret_snode, smb_fssd_t *fs_sd)
 125 {
 126         vsecattr_t *vsap;
 127         vsecattr_t vsecattr;
 128         smb_attr_t set_attr;
 129         acl_t *acl, *dacl, *sacl;
 130         vnode_t *vp;
 131         cred_t *kcr = zone_kcred();
 132         int aclbsize = 0;       /* size of acl list in bytes */
 133         int flags = 0;
 134         int rc;
 135         boolean_t is_dir;
 136 
 137         ASSERT(fs_sd);
 138 
 139         if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 140                 flags = SMB_IGNORE_CASE;
 141         if (SMB_TREE_SUPPORTS_CATIA(sr))
 142                 flags |= SMB_CATIA;
 143 
 144         ASSERT(cr);
 145 
 146         is_dir = ((fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) != 0);
 147 
 148         if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_ACLONCREATE)) {
 149                 if (fs_sd->sd_secinfo & SMB_ACL_SECINFO) {
 150                         dacl = fs_sd->sd_zdacl;
 151                         sacl = fs_sd->sd_zsacl;
 152                         ASSERT(dacl || sacl);
 153                         if (dacl && sacl) {
 154                                 acl = smb_fsacl_merge(dacl, sacl);
 155                         } else if (dacl) {
 156                                 acl = dacl;
 157                         } else {
 158                                 acl = sacl;
 159                         }
 160 
 161                         rc = smb_fsacl_to_vsa(acl, &vsecattr, &aclbsize);
 162 
 163                         if (dacl && sacl)
 164                                 acl_free(acl);
 165 
 166                         if (rc != 0)
 167                                 return (rc);
 168 
 169                         vsap = &vsecattr;
 170                 } else {
 171                         vsap = NULL;
 172                 }
 173 
 174                 /* The tree ACEs may prevent a create */
 175                 rc = EACCES;
 176                 if (is_dir) {
 177                         if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_SUBDIRECTORY) != 0)
 178                                 rc = smb_vop_mkdir(dnode->vp, name, attr,
 179                                     &vp, flags, cr, vsap);
 180                 } else {
 181                         if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_FILE) != 0)
 182                                 rc = smb_vop_create(dnode->vp, name, attr,
 183                                     &vp, flags, cr, vsap);
 184                 }
 185 
 186                 if (vsap != NULL)
 187                         kmem_free(vsap->vsa_aclentp, aclbsize);
 188 
 189                 if (rc != 0)
 190                         return (rc);
 191 
 192                 set_attr.sa_mask = 0;
 193 
 194                 /*
 195                  * Ideally we should be able to specify the owner and owning
 196                  * group at create time along with the ACL. Since we cannot
 197                  * do that right now, kcred is passed to smb_vop_setattr so it
 198                  * doesn't fail due to lack of permission.
 199                  */
 200                 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
 201                         set_attr.sa_vattr.va_uid = fs_sd->sd_uid;
 202                         set_attr.sa_mask |= SMB_AT_UID;
 203                 }
 204 
 205                 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
 
 220                         VN_RELE(vp);
 221                 }
 222         } else {
 223                 /*
 224                  * For filesystems that don't support ACL-on-create, try
 225                  * to set the specified SD after create, which could actually
 226                  * fail because of conflicts between inherited security
 227                  * attributes upon creation and the specified SD.
 228                  *
 229                  * Passing kcred to smb_fsop_sdwrite() to overcome this issue.
 230                  */
 231 
 232                 if (is_dir) {
 233                         rc = smb_vop_mkdir(dnode->vp, name, attr, &vp,
 234                             flags, cr, NULL);
 235                 } else {
 236                         rc = smb_vop_create(dnode->vp, name, attr, &vp,
 237                             flags, cr, NULL);
 238                 }
 239 
 240                 if (rc != 0)
 241                         return (rc);
 242 
 243                 *ret_snode = smb_node_lookup(sr, &sr->arg.open, cr, vp,
 244                     name, dnode, NULL);
 245 
 246                 if (*ret_snode != NULL) {
 247                         if (!smb_tree_has_feature(sr->tid_tree,
 248                             SMB_TREE_NFS_MOUNTED))
 249                                 rc = smb_fsop_sdwrite(sr, kcr, *ret_snode,
 250                                     fs_sd, 1);
 251                 } else {
 252                         rc = ENOMEM;
 253                 }
 254 
 255                 VN_RELE(vp);
 256         }
 257 
 258         if (rc != 0) {
 259                 if (is_dir)
 
 302         ASSERT(sr->tid_tree);
 303 
 304         if (SMB_TREE_CONTAINS_NODE(sr, dnode) == 0)
 305                 return (EACCES);
 306 
 307         if (SMB_TREE_IS_READONLY(sr))
 308                 return (EROFS);
 309 
 310         if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 311                 flags = SMB_IGNORE_CASE;
 312         if (SMB_TREE_SUPPORTS_CATIA(sr))
 313                 flags |= SMB_CATIA;
 314         if (SMB_TREE_SUPPORTS_ABE(sr))
 315                 flags |= SMB_ABE;
 316 
 317         if (smb_is_stream_name(name)) {
 318                 fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 319                 sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 320                 smb_stream_parse_name(name, fname, sname);
 321 
 322                 rc = smb_fsop_create_stream(sr, cr, dnode,
 323                     fname, sname, flags, attr, ret_snode);
 324 
 325                 kmem_free(fname, MAXNAMELEN);
 326                 kmem_free(sname, MAXNAMELEN);
 327                 return (rc);
 328         }
 329 
 330         /* Not a named stream */
 331 
 332         if (SMB_TREE_SUPPORTS_SHORTNAMES(sr) && smb_maybe_mangled(name)) {
 333                 longname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 334                 rc = smb_unmangle(dnode, name, longname, MAXNAMELEN, flags);
 335                 kmem_free(longname, MAXNAMELEN);
 336 
 337                 if (rc == 0)
 338                         rc = EEXIST;
 339                 if (rc != ENOENT)
 340                         return (rc);
 341         }
 342 
 343         rc = smb_fsop_create_file(sr, cr, dnode, name, flags,
 344             attr, ret_snode);
 345         return (rc);
 346 
 347 }
 348 
 349 
 350 /*
 351  * smb_fsop_create_stream
 352  *
 353  * Create NTFS named stream file (sname) on unnamed stream
 354  * file (fname), creating the unnamed stream file if it
 355  * doesn't exist.
 356  * If we created the unnamed stream file and then creation
 357  * of the named stream file fails, we delete the unnamed stream.
 358  * Since we use the real file name for the smb_vop_remove we
 359  * clear the SMB_IGNORE_CASE flag to ensure a case sensitive
 360  * match.
 361  *
 362  * The second parameter of smb_vop_setattr() is set to
 363  * NULL, even though an unnamed stream exists.  This is
 364  * because we want to set the UID and GID on the named
 365  * stream in this case for consistency with the (unnamed
 366  * stream) file (see comments for smb_vop_setattr()).
 367  */
 368 static int
 369 smb_fsop_create_stream(smb_request_t *sr, cred_t *cr,
 370     smb_node_t *dnode, char *fname, char *sname, int flags,
 371     smb_attr_t *attr, smb_node_t **ret_snode)
 372 {
 373         smb_attr_t      fattr;
 374         smb_node_t      *fnode;
 375         vnode_t         *xattrdvp;
 376         vnode_t         *vp;
 377         cred_t          *kcr = zone_kcred();
 378         int             rc = 0;
 379         boolean_t       fcreate = B_FALSE;
 380 
 381         /* Look up / create the unnamed stream, fname */
 382         rc = smb_fsop_lookup(sr, cr, flags | SMB_FOLLOW_LINKS,
 383             sr->tid_tree->t_snode, dnode, fname, &fnode);
 384         if (rc == ENOENT) {
 385                 fcreate = B_TRUE;
 386                 rc = smb_fsop_create_file(sr, cr, dnode, fname, flags,
 387                     attr, &fnode);
 388         }
 389         if (rc != 0)
 390                 return (rc);
 391 
 392         fattr.sa_mask = SMB_AT_UID | SMB_AT_GID;
 393         rc = smb_vop_getattr(fnode->vp, NULL, &fattr, 0, kcr);
 394 
 395         if (rc == 0) {
 396                 /* create the named stream, sname */
 397                 rc = smb_vop_stream_create(fnode->vp, sname, attr,
 398                     &vp, &xattrdvp, flags, cr);
 399         }
 400         if (rc != 0) {
 401                 if (fcreate) {
 402                         flags &= ~SMB_IGNORE_CASE;
 403                         (void) smb_vop_remove(dnode->vp,
 404                             fnode->od_name, flags, cr);
 405                 }
 406                 smb_node_release(fnode);
 407                 return (rc);
 408         }
 409 
 410         attr->sa_vattr.va_uid = fattr.sa_vattr.va_uid;
 411         attr->sa_vattr.va_gid = fattr.sa_vattr.va_gid;
 412         attr->sa_mask = SMB_AT_UID | SMB_AT_GID;
 413 
 414         rc = smb_vop_setattr(vp, NULL, attr, 0, kcr);
 415         if (rc != 0) {
 416                 smb_node_release(fnode);
 417                 return (rc);
 418         }
 419 
 420         *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdvp,
 421             vp, sname);
 422 
 423         smb_node_release(fnode);
 424         VN_RELE(xattrdvp);
 425         VN_RELE(vp);
 426 
 427         if (*ret_snode == NULL)
 428                 rc = ENOMEM;
 429 
 430         /* notify change to the unnamed stream */
 431         if (rc == 0)
 432                 smb_node_notify_change(dnode,
 433                     FILE_ACTION_ADDED_STREAM, fname);
 434 
 435         return (rc);
 436 }
 437 
 438 /*
 439  * smb_fsop_create_file
 440  */
 441 static int
 442 smb_fsop_create_file(smb_request_t *sr, cred_t *cr,
 443     smb_node_t *dnode, char *name, int flags,
 444     smb_attr_t *attr, smb_node_t **ret_snode)
 445 {
 446         smb_arg_open_t  *op = &sr->sr_open;
 447         vnode_t         *vp;
 448         int             rc;
 449 
 450 #ifdef  _KERNEL
 451         smb_fssd_t      fs_sd;
 452         uint32_t        secinfo;
 453         uint32_t        status;
 454 
 455         if (op->sd) {
 456                 /*
 457                  * SD sent by client in Windows format. Needs to be
 458                  * converted to FS format. No inheritance.
 459                  */
 460                 secinfo = smb_sd_get_secinfo(op->sd);
 461                 smb_fssd_init(&fs_sd, secinfo, 0);
 462 
 463                 status = smb_sd_tofs(op->sd, &fs_sd);
 464                 if (status == NT_STATUS_SUCCESS) {
 465                         rc = smb_fsop_create_with_sd(sr, cr, dnode,
 466                             name, attr, ret_snode, &fs_sd);
 467                 } else {
 468                         rc = EINVAL;
 469                 }
 
 471         } else if (sr->tid_tree->t_acltype == ACE_T) {
 472                 /*
 473                  * No incoming SD and filesystem is ZFS
 474                  * Server applies Windows inheritance rules,
 475                  * see smb_fsop_sdinherit() comments as to why.
 476                  */
 477                 smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, 0);
 478                 rc = smb_fsop_sdinherit(sr, dnode, &fs_sd);
 479                 if (rc == 0) {
 480                         rc = smb_fsop_create_with_sd(sr, cr, dnode,
 481                             name, attr, ret_snode, &fs_sd);
 482                 }
 483 
 484                 smb_fssd_term(&fs_sd);
 485         } else
 486 #endif  /* _KERNEL */
 487         {
 488                 /*
 489                  * No incoming SD and filesystem is not ZFS
 490                  * let the filesystem handles the inheritance.
 491                  */
 492                 rc = smb_vop_create(dnode->vp, name, attr, &vp,
 493                     flags, cr, NULL);
 494 
 495                 if (rc == 0) {
 496                         *ret_snode = smb_node_lookup(sr, op, cr, vp,
 497                             name, dnode, NULL);
 498 
 499                         if (*ret_snode == NULL)
 500                                 rc = ENOMEM;
 501 
 502                         VN_RELE(vp);
 503                 }
 504 
 505         }
 506 
 507         if (rc == 0)
 508                 smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
 509 
 510         return (rc);
 511 }
 512 
 513 /*
 514  * smb_fsop_mkdir
 
 610                         rc = EINVAL;
 611                 smb_fssd_term(&fs_sd);
 612         } else if (sr->tid_tree->t_acltype == ACE_T) {
 613                 /*
 614                  * No incoming SD and filesystem is ZFS
 615                  * Server applies Windows inheritance rules,
 616                  * see smb_fsop_sdinherit() comments as to why.
 617                  */
 618                 smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, SMB_FSSD_FLAGS_DIR);
 619                 rc = smb_fsop_sdinherit(sr, dnode, &fs_sd);
 620                 if (rc == 0) {
 621                         rc = smb_fsop_create_with_sd(sr, cr, dnode,
 622                             name, attr, ret_snode, &fs_sd);
 623                 }
 624 
 625                 smb_fssd_term(&fs_sd);
 626 
 627         } else
 628 #endif  /* _KERNEL */
 629         {
 630                 rc = smb_vop_mkdir(dnode->vp, name, attr, &vp, flags, cr,
 631                     NULL);
 632 
 633                 if (rc == 0) {
 634                         *ret_snode = smb_node_lookup(sr, op, cr, vp, name,
 635                             dnode, NULL);
 636 
 637                         if (*ret_snode == NULL)
 638                                 rc = ENOMEM;
 639 
 640                         VN_RELE(vp);
 641                 }
 642         }
 643 
 644         if (rc == 0)
 645                 smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
 646 
 647         return (rc);
 648 }
 649 
 650 /*
 651  * smb_fsop_remove
 652  *
 653  * All SMB functions should use this wrapper to ensure that
 654  * the the calls are performed with the appropriate credentials.
 655  * Please document any direct call to explain the reason
 656  * for avoiding this wrapper.
 657  *
 658  * It is assumed that a reference exists on snode coming into this routine.
 659  *
 660  * A null smb_request might be passed to this function.
 661  */
 662 int
 663 smb_fsop_remove(
 664     smb_request_t       *sr,
 665     cred_t              *cr,
 666     smb_node_t          *dnode,
 667     char                *name,
 668     uint32_t            flags)
 669 {
 670         smb_node_t      *fnode;
 671         char            *longname;
 672         char            *fname;
 673         char            *sname;
 674         int             rc;
 675 
 676         ASSERT(cr);
 677         /*
 678          * The state of the node could be SMB_NODE_STATE_DESTROYING if this
 679          * function is called during the deletion of the node (because of
 680          * DELETE_ON_CLOSE).
 681          */
 682         ASSERT(dnode);
 683         ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
 684 
 685         if (SMB_TREE_CONTAINS_NODE(sr, dnode) == 0 ||
 686             SMB_TREE_HAS_ACCESS(sr, ACE_DELETE) == 0)
 687                 return (EACCES);
 688 
 689         if (SMB_TREE_IS_READONLY(sr))
 690                 return (EROFS);
 691 
 692         fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 693         sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 694 
 695         if (dnode->flags & NODE_XATTR_DIR) {
 696                 fnode = dnode->n_dnode;
 697                 rc = smb_vop_stream_remove(fnode->vp, name, flags, cr);
 698 
 699                 /* notify change to the unnamed stream */
 700                 if ((rc == 0) && fnode->n_dnode) {
 701                         smb_node_notify_change(fnode->n_dnode,
 702                             FILE_ACTION_REMOVED_STREAM, fnode->od_name);
 703                 }
 704         } else if (smb_is_stream_name(name)) {
 705                 smb_stream_parse_name(name, fname, sname);
 706 
 707                 /*
 708                  * Look up the unnamed stream (i.e. fname).
 709                  * Unmangle processing will be done on fname
 710                  * as well as any link target.
 711                  */
 712 
 713                 rc = smb_fsop_lookup(sr, cr, flags | SMB_FOLLOW_LINKS,
 714                     sr->tid_tree->t_snode, dnode, fname, &fnode);
 715 
 716                 if (rc != 0) {
 717                         kmem_free(fname, MAXNAMELEN);
 718                         kmem_free(sname, MAXNAMELEN);
 719                         return (rc);
 720                 }
 721 
 722                 /*
 723                  * XXX
 724                  * Need to find out what permission is required by NTFS
 725                  * to remove a stream.
 726                  */
 727                 rc = smb_vop_stream_remove(fnode->vp, sname, flags, cr);
 728 
 729                 smb_node_release(fnode);
 730 
 731                 /* notify change to the unnamed stream */
 732                 if (rc == 0) {
 733                         smb_node_notify_change(dnode,
 734                             FILE_ACTION_REMOVED_STREAM, fname);
 735                 }
 736         } else {
 737                 rc = smb_vop_remove(dnode->vp, name, flags, cr);
 738 
 739                 if (rc == ENOENT) {
 740                         if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
 741                             !smb_maybe_mangled(name)) {
 742                                 kmem_free(fname, MAXNAMELEN);
 743                                 kmem_free(sname, MAXNAMELEN);
 744                                 return (rc);
 745                         }
 746                         longname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 747 
 748                         if (SMB_TREE_SUPPORTS_ABE(sr))
 749                                 flags |= SMB_ABE;
 750 
 751                         rc = smb_unmangle(dnode, name, longname, MAXNAMELEN,
 752                             flags);
 753 
 754                         if (rc == 0) {
 755                                 /*
 756                                  * longname is the real (case-sensitive)
 757                                  * on-disk name.
 758                                  * We make sure we do a remove on this exact
 759                                  * name, as the name was mangled and denotes
 760                                  * a unique file.
 761                                  */
 762                                 flags &= ~SMB_IGNORE_CASE;
 763                                 rc = smb_vop_remove(dnode->vp, longname,
 764                                     flags, cr);
 765                         }
 766                         kmem_free(longname, MAXNAMELEN);
 767                 }
 768                 if (rc == 0) {
 769                         smb_node_notify_change(dnode,
 770                             FILE_ACTION_REMOVED, name);
 771                 }
 772         }
 773 
 774         kmem_free(fname, MAXNAMELEN);
 775         kmem_free(sname, MAXNAMELEN);
 776 
 777         return (rc);
 778 }
 779 
 780 /*
 781  * smb_fsop_remove_streams
 782  *
 783  * This function removes a file's streams without removing the
 784  * file itself.
 785  *
 786  * It is assumed that fnode is not a link.
 787  */
 788 uint32_t
 789 smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode)
 790 {
 791         int rc, flags = 0;
 792         smb_odir_t *od;
 793         smb_odirent_t *odirent;
 
 799         ASSERT(fnode);
 800         ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
 801         ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
 802 
 803         if (SMB_TREE_CONTAINS_NODE(sr, fnode) == 0)
 804                 return (NT_STATUS_ACCESS_DENIED);
 805 
 806         if (SMB_TREE_IS_READONLY(sr))
 807                 return (NT_STATUS_ACCESS_DENIED);
 808 
 809         if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 810                 flags = SMB_IGNORE_CASE;
 811 
 812         if (SMB_TREE_SUPPORTS_CATIA(sr))
 813                 flags |= SMB_CATIA;
 814 
 815         status = smb_odir_openat(sr, fnode, &od);
 816         switch (status) {
 817         case 0:
 818                 break;
 819         case NT_STATUS_NO_SUCH_FILE:
 820         case NT_STATUS_NOT_SUPPORTED:
 821                 /* No streams to remove. */
 822                 return (0);
 823         default:
 824                 return (status);
 825         }
 826 
 827         odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
 828         for (;;) {
 829                 rc = smb_odir_read(sr, od, odirent, &eos);
 830                 if ((rc != 0) || (eos))
 831                         break;
 832                 (void) smb_vop_remove(od->d_dnode->vp, odirent->od_name,
 833                     flags, cr);
 834         }
 835         kmem_free(odirent, sizeof (smb_odirent_t));
 836         if (eos && rc == ENOENT)
 837                 rc = 0;
 838 
 
1097         /*
1098          * Note: There is no need to check SMB_TREE_IS_CASEINSENSITIVE
1099          * here.
1100          *
1101          * A case-sensitive rename is always done in this routine
1102          * because we are using the on-disk name from an earlier lookup.
1103          * If a mangled name was passed in by the caller (denoting a
1104          * deterministic lookup), then the exact file must be renamed
1105          * (i.e. SMB_IGNORE_CASE must not be passed to VOP_RENAME, or
1106          * else the underlying file system might return a "first-match"
1107          * on this on-disk name, possibly resulting in the wrong file).
1108          */
1109 
1110         if (SMB_TREE_SUPPORTS_CATIA(sr))
1111                 flags |= SMB_CATIA;
1112 
1113         /*
1114          * XXX: Lock required through smb_node_release() below?
1115          */
1116 
1117         rc = smb_vop_lookup(from_dnode->vp, from_name, &from_vp, NULL,
1118             flags, &ret_flags, NULL, &from_attr, cr);
1119 
1120         if (rc != 0)
1121                 return (rc);
1122 
1123         if (from_attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) {
1124                 VN_RELE(from_vp);
1125                 return (EACCES);
1126         }
1127 
1128         isdir = ((from_attr.sa_dosattr & FILE_ATTRIBUTE_DIRECTORY) != 0);
1129 
1130         if ((isdir && SMB_TREE_HAS_ACCESS(sr,
1131             ACE_DELETE_CHILD | ACE_ADD_SUBDIRECTORY) !=
1132             (ACE_DELETE_CHILD | ACE_ADD_SUBDIRECTORY)) ||
1133             (!isdir && SMB_TREE_HAS_ACCESS(sr, ACE_DELETE | ACE_ADD_FILE) !=
1134             (ACE_DELETE | ACE_ADD_FILE))) {
1135                 VN_RELE(from_vp);
1136                 return (EACCES);
1137         }
1138 
1139         /*
1140          * SMB checks access on open and retains an access granted
1141          * mask for use while the file is open.  ACL changes should
1142          * not affect access to an open file.
1143          *
1144          * If the rename is being performed on an ofile:
1145          * - Check the ofile's access granted mask to see if the
1146          *   rename is permitted - requires DELETE access.
1147          * - If the file system does access checking, set the
1148          *   ATTR_NOACLCHECK flag to ensure that the file system
1149          *   does not check permissions on subsequent calls.
1150          */
1151         if (sr && sr->fid_ofile) {
1152                 rc = smb_ofile_access(sr->fid_ofile, cr, DELETE);
1153                 if (rc != NT_STATUS_SUCCESS) {
1154                         VN_RELE(from_vp);
1155                         return (EACCES);
1156                 }
1157 
1158                 if (smb_tree_has_feature(sr->tid_tree,
1159                     SMB_TREE_ACEMASKONACCESS))
1160                         flags = ATTR_NOACLCHECK;
1161         }
1162 
1163         rc = smb_vop_rename(from_dnode->vp, from_name, to_dnode->vp,
1164             to_name, flags, cr);
1165 
1166         if (rc == 0) {
1167                 from_snode = smb_node_lookup(sr, NULL, cr, from_vp, from_name,
1168                     from_dnode, NULL);
1169 
1170                 if (from_snode == NULL) {
1171                         rc = ENOMEM;
1172                 } else {
1173                         smb_node_rename(from_dnode, from_snode,
1174                             to_dnode, to_name);
1175                         smb_node_release(from_snode);
1176                 }
1177         }
 
1222         int rc = 0;
1223         int flags = 0;
1224         uint_t sa_mask;
1225 
1226         ASSERT(cr);
1227         ASSERT(snode);
1228         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1229         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1230 
1231         if (SMB_TREE_CONTAINS_NODE(sr, snode) == 0)
1232                 return (EACCES);
1233 
1234         if (SMB_TREE_IS_READONLY(sr))
1235                 return (EROFS);
1236 
1237         if (SMB_TREE_HAS_ACCESS(sr,
1238             ACE_WRITE_ATTRIBUTES | ACE_WRITE_NAMED_ATTRS) == 0)
1239                 return (EACCES);
1240 
1241         /*
1242          * The file system cannot detect pending READDONLY
1243          * (i.e. if the file has been opened readonly but
1244          * not yet closed) so we need to test READONLY here.
1245          *
1246          * Note that file handle that were opened before the
1247          * READONLY flag was set in the node (or the FS) are
1248          * immune to that change, and remain writable.
1249          */
1250         if (sr && (set_attr->sa_mask & SMB_AT_SIZE)) {
1251                 if (sr->fid_ofile) {
1252                         if (SMB_OFILE_IS_READONLY(sr->fid_ofile))
1253                                 return (EACCES);
1254                 } else {
1255                         if (SMB_PATHFILE_IS_READONLY(sr, snode))
1256                                 return (EACCES);
1257                 }
1258         }
1259 
1260         /*
1261          * SMB checks access on open and retains an access granted
1262          * mask for use while the file is open.  ACL changes should
1263          * not affect access to an open file.
1264          *
1265          * If the setattr is being performed on an ofile:
1266          * - Check the ofile's access granted mask to see if the
1267          *   setattr is permitted.
1268          *   UID, GID - require WRITE_OWNER
1269          *   SIZE, ALLOCSZ - require FILE_WRITE_DATA
1270          *   all other attributes require FILE_WRITE_ATTRIBUTES
1271          *
1272          * - If the file system does access checking, set the
1273          *   ATTR_NOACLCHECK flag to ensure that the file system
1274          *   does not check permissions on subsequent calls.
1275          */
1276         if (sr && sr->fid_ofile) {
1277                 sa_mask = set_attr->sa_mask;
1278                 access = 0;
1279 
1280                 if (sa_mask & (SMB_AT_SIZE | SMB_AT_ALLOCSZ)) {
 
1296 
1297                 if (smb_tree_has_feature(sr->tid_tree,
1298                     SMB_TREE_ACEMASKONACCESS))
1299                         flags = ATTR_NOACLCHECK;
1300         }
1301 
1302         unnamed_node = SMB_IS_STREAM(snode);
1303 
1304         if (unnamed_node) {
1305                 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
1306                 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1307                 unnamed_vp = unnamed_node->vp;
1308         }
1309 
1310         rc = smb_vop_setattr(snode->vp, unnamed_vp, set_attr, flags, cr);
1311         return (rc);
1312 }
1313 
1314 /*
1315  * Support for SMB2 setinfo FileValidDataLengthInformation.
1316  * Free data from the specified offset to EoF.
1317  *
1318  * This can effectively truncate data.  It truncates the data
1319  * leaving the file size as it was, leaving zeros after the
1320  * offset specified here.  That is effectively modifying the
1321  * file content, so for access control this is a write.
1322  */
1323 int
1324 smb_fsop_set_data_length(
1325     smb_request_t       *sr,
1326     cred_t              *cr,
1327     smb_node_t          *node,
1328     offset_t            end_of_data)
1329 {
1330         flock64_t flk;
1331         uint32_t status;
1332         uint32_t access = FILE_WRITE_DATA;
1333         int rc;
1334 
1335         ASSERT(cr);
1336         ASSERT(node);
1337         ASSERT(node->n_magic == SMB_NODE_MAGIC);
1338         ASSERT(node->n_state != SMB_NODE_STATE_DESTROYING);
1339 
1340         if (SMB_TREE_CONTAINS_NODE(sr, node) == 0)
1341                 return (EACCES);
1342 
1343         if (SMB_TREE_IS_READONLY(sr))
1344                 return (EROFS);
1345 
1346         if (SMB_TREE_HAS_ACCESS(sr, access) == 0)
1347                 return (EACCES);
1348 
1349         /*
1350          * The file system cannot detect pending READDONLY
1351          * (i.e. if the file has been opened readonly but
1352          * not yet closed) so we need to test READONLY here.
1353          *
1354          * Note that file handle that were opened before the
1355          * READONLY flag was set in the node (or the FS) are
1356          * immune to that change, and remain writable.
1357          */
1358         if (sr->fid_ofile) {
1359                 if (SMB_OFILE_IS_READONLY(sr->fid_ofile))
1360                         return (EACCES);
1361         } else {
1362                 /* This requires an open file. */
1363                 return (EACCES);
1364         }
1365 
1366         /*
1367          * SMB checks access on open and retains an access granted
1368          * mask for use while the file is open.  ACL changes should
1369          * not affect access to an open file.
1370          *
1371          * If the setattr is being performed on an ofile:
1372          * - Check the ofile's access granted mask to see if this
1373          *   modification should be permitted (FILE_WRITE_DATA)
1374          */
1375         status = smb_ofile_access(sr->fid_ofile, cr, access);
1376         if (status != NT_STATUS_SUCCESS)
1377                 return (EACCES);
1378 
1379         bzero(&flk, sizeof (flk));
1380         flk.l_start = end_of_data;
1381 
1382         rc = smb_vop_space(node->vp, F_FREESP, &flk, FWRITE, 0LL, cr);
1383         return (rc);
1384 }
1385 
1386 /*
1387  * smb_fsop_read
1388  *
1389  * All SMB functions should use this wrapper to ensure that
1390  * the the calls are performed with the appropriate credentials.
1391  * Please document any direct call to explain the reason
1392  * for avoiding this wrapper.
1393  *
1394  * It is assumed that a reference exists on snode coming into this routine.
1395  */
1396 int
1397 smb_fsop_read(smb_request_t *sr, cred_t *cr, smb_node_t *snode, uio_t *uio)
1398 {
1399         caller_context_t ct;
1400         cred_t *kcr = zone_kcred();
1401         int svmand;
1402         int rc;
1403 
1404         ASSERT(cr);
1405         ASSERT(snode);
1406         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1407         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1408 
1409         ASSERT(sr);
1410         ASSERT(sr->fid_ofile);
1411 
1412         if (SMB_TREE_HAS_ACCESS(sr, ACE_READ_DATA) == 0)
1413                 return (EACCES);
1414 
1415         rc = smb_ofile_access(sr->fid_ofile, cr, FILE_READ_DATA);
1416         if ((rc != NT_STATUS_SUCCESS) &&
1417             (sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE))
1418                 rc = smb_ofile_access(sr->fid_ofile, cr, FILE_EXECUTE);
1419 
1420         if (rc != NT_STATUS_SUCCESS)
1421                 return (EACCES);
1422 
1423         /*
1424          * Streams permission are checked against the unnamed stream,
1425          * but in FS level they have their own permissions. To avoid
1426          * rejection by FS due to lack of permission on the actual
1427          * extended attr kcred is passed for streams.
1428          */
1429         if (SMB_IS_STREAM(snode))
1430                 cr = kcr;
1431 
1432         smb_node_start_crit(snode, RW_READER);
1433         rc = nbl_svmand(snode->vp, kcr, &svmand);
1434         if (rc) {
1435                 smb_node_end_crit(snode);
1436                 return (rc);
1437         }
1438 
1439         ct = smb_ct;
1440         ct.cc_pid = sr->fid_ofile->f_uniqid;
1441         rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset,
1442             uio->uio_iov->iov_len, svmand, &ct);
1443 
1444         if (rc) {
1445                 smb_node_end_crit(snode);
1446                 return (ERANGE);
1447         }
1448 
1449         rc = smb_vop_read(snode->vp, uio, cr);
1450         smb_node_end_crit(snode);
1451 
1452         return (rc);
1453 }
1454 
1455 /*
1456  * smb_fsop_write
1457  *
1458  * This is a wrapper function used for smb_write and smb_write_raw operations.
1459  *
1460  * It is assumed that a reference exists on snode coming into this routine.
1461  */
1462 int
1463 smb_fsop_write(
1464     smb_request_t *sr,
1465     cred_t *cr,
1466     smb_node_t *snode,
1467     uio_t *uio,
1468     uint32_t *lcount,
1469     int ioflag)
1470 {
1471         caller_context_t ct;
1472         smb_attr_t attr;
1473         smb_node_t *u_node;
1474         vnode_t *u_vp = NULL;
1475         smb_ofile_t *of;
1476         vnode_t *vp;
1477         cred_t *kcr = zone_kcred();
1478         int svmand;
1479         int rc;
1480 
1481         ASSERT(cr);
1482         ASSERT(snode);
1483         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1484         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1485 
1486         ASSERT(sr);
1487         ASSERT(sr->tid_tree);
1488         of = sr->fid_ofile;
1489         vp = snode->vp;
1490 
1491         if (SMB_TREE_IS_READONLY(sr))
1492                 return (EROFS);
1493 
1494         if (SMB_OFILE_IS_READONLY(of) ||
1495             SMB_TREE_HAS_ACCESS(sr, ACE_WRITE_DATA | ACE_APPEND_DATA) == 0)
1496                 return (EACCES);
1497 
1498         rc = smb_ofile_access(of, cr, FILE_WRITE_DATA);
1499         if (rc != NT_STATUS_SUCCESS) {
1500                 rc = smb_ofile_access(of, cr, FILE_APPEND_DATA);
1501                 if (rc != NT_STATUS_SUCCESS)
1502                         return (EACCES);
1503         }
1504 
1505         /*
1506          * Streams permission are checked against the unnamed stream,
1507          * but in FS level they have their own permissions. To avoid
1508          * rejection by FS due to lack of permission on the actual
1509          * extended attr kcred is passed for streams.
1510          */
1511         u_node = SMB_IS_STREAM(snode);
1512         if (u_node != NULL) {
1513                 ASSERT(u_node->n_magic == SMB_NODE_MAGIC);
1514                 ASSERT(u_node->n_state != SMB_NODE_STATE_DESTROYING);
1515                 u_vp = u_node->vp;
1516                 cr = kcr;
1517         }
1518 
1519         smb_node_start_crit(snode, RW_WRITER);
1520         rc = nbl_svmand(vp, kcr, &svmand);
1521         if (rc) {
1522                 smb_node_end_crit(snode);
1523                 return (rc);
1524         }
1525 
1526         ct = smb_ct;
1527         ct.cc_pid = of->f_uniqid;
1528         rc = nbl_lock_conflict(vp, NBL_WRITE, uio->uio_loffset,
1529             uio->uio_iov->iov_len, svmand, &ct);
1530 
1531         if (rc) {
1532                 smb_node_end_crit(snode);
1533                 return (ERANGE);
1534         }
1535 
1536         rc = smb_vop_write(vp, uio, ioflag, lcount, cr);
1537 
1538         /*
1539          * Once the mtime has been set via this ofile, the
1540          * automatic mtime changes from writes via this ofile
1541          * should cease, preserving the mtime that was set.
1542          * See: [MS-FSA] 2.1.5.14 and smb_node_setattr.
1543          *
1544          * The VFS interface does not offer a way to ask it to
1545          * skip the mtime updates, so we simulate the desired
1546          * behavior by re-setting the mtime after writes on a
1547          * handle where the mtime has been set.
1548          */
1549         if (of->f_pending_attr.sa_mask & SMB_AT_MTIME) {
1550                 bcopy(&of->f_pending_attr, &attr, sizeof (attr));
1551                 attr.sa_mask = SMB_AT_MTIME;
1552                 (void) smb_vop_setattr(vp, u_vp, &attr, 0, kcr);
1553         }
1554 
1555         smb_node_end_crit(snode);
1556 
1557         return (rc);
1558 }
1559 
1560 /*
1561  * smb_fsop_statfs
1562  *
1563  * This is a wrapper function used for stat operations.
1564  */
1565 int
1566 smb_fsop_statfs(
1567     cred_t *cr,
1568     smb_node_t *snode,
1569     struct statvfs64 *statp)
1570 {
1571         ASSERT(cr);
1572         ASSERT(snode);
1573         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1574         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1575 
1576         return (smb_vop_statfs(snode->vp, statp, cr));
1577 }
1578 
1579 /*
1580  * smb_fsop_access
1581  *
1582  * Named streams do not have separate permissions from the associated
1583  * unnamed stream.  Thus, if node is a named stream, the permissions
1584  * check will be performed on the associated unnamed stream.
1585  *
1586  * However, our named streams do have their own quarantine attribute,
1587  * separate from that on the unnamed stream. If READ or EXECUTE
1588  * access has been requested on a named stream, an additional access
1589  * check is performed on the named stream in case it has been
1590  * quarantined.  kcred is used to avoid issues with the permissions
1591  * set on the extended attribute file representing the named stream.
1592  */
1593 int
1594 smb_fsop_access(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
1595     uint32_t faccess)
1596 {
1597         int access = 0;
1598         int error;
1599         vnode_t *dir_vp;
1600         boolean_t acl_check = B_TRUE;
1601         smb_node_t *unnamed_node;
1602 
1603         ASSERT(sr);
1604         ASSERT(cr);
1605         ASSERT(snode);
1606         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1607         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1608 
1609         if (SMB_TREE_IS_READONLY(sr)) {
1610                 if (faccess & (FILE_WRITE_DATA|FILE_APPEND_DATA|
1611                     FILE_WRITE_EA|FILE_DELETE_CHILD|FILE_WRITE_ATTRIBUTES|
1612                     DELETE|WRITE_DAC|WRITE_OWNER)) {
1613                         return (NT_STATUS_ACCESS_DENIED);
1614                 }
1615         }
1616 
1617         if (smb_node_is_reparse(snode) && (faccess & DELETE))
1618                 return (NT_STATUS_ACCESS_DENIED);
1619 
1620         unnamed_node = SMB_IS_STREAM(snode);
1621         if (unnamed_node) {
1622                 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
1623                 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1624 
1625                 /*
1626                  * Perform VREAD access check on the named stream in case it
1627                  * is quarantined. kcred is passed to smb_vop_access so it
1628                  * doesn't fail due to lack of permission.
1629                  */
1630                 if (faccess & (FILE_READ_DATA | FILE_EXECUTE)) {
1631                         error = smb_vop_access(snode->vp, VREAD,
1632                             0, NULL, zone_kcred());
1633                         if (error)
1634                                 return (NT_STATUS_ACCESS_DENIED);
1635                 }
1636 
1637                 /*
1638                  * Streams authorization should be performed against the
1639                  * unnamed stream.
1640                  */
1641                 snode = unnamed_node;
1642         }
1643 
1644         if (faccess & ACCESS_SYSTEM_SECURITY) {
1645                 /*
1646                  * This permission is required for reading/writing SACL and
1647                  * it's not part of DACL. It's only granted via proper
1648                  * privileges.
1649                  */
1650                 if ((sr->uid_user->u_privileges &
1651                     (SMB_USER_PRIV_BACKUP |
1652                     SMB_USER_PRIV_RESTORE |
 
1675                  * FS doesn't understand 32-bit mask, need to map
1676                  */
1677                 if (faccess & (FILE_WRITE_DATA | FILE_APPEND_DATA))
1678                         access |= VWRITE;
1679 
1680                 if (faccess & FILE_READ_DATA)
1681                         access |= VREAD;
1682 
1683                 if (faccess & FILE_EXECUTE)
1684                         access |= VEXEC;
1685 
1686                 error = smb_vop_access(snode->vp, access, 0, NULL, cr);
1687         }
1688 
1689         return ((error) ? NT_STATUS_ACCESS_DENIED : NT_STATUS_SUCCESS);
1690 }
1691 
1692 /*
1693  * smb_fsop_lookup_name()
1694  *
1695  * If name indicates that the file is a stream file, perform
1696  * stream specific lookup, otherwise call smb_fsop_lookup.
1697  *
1698  * Return an error if the looked-up file is in outside the tree.
1699  * (Required when invoked from open path.)
1700  *
1701  * Case sensitivity flags (SMB_IGNORE_CASE, SMB_CASE_SENSITIVE):
1702  * if SMB_CASE_SENSITIVE is set, the SMB_IGNORE_CASE flag will NOT be set
1703  * based on the tree's case sensitivity. However, if the SMB_IGNORE_CASE
1704  * flag is set in the flags value passed as a parameter, a case insensitive
1705  * lookup WILL be done (regardless of whether SMB_CASE_SENSITIVE is set
1706  * or not).
1707  */
1708 
1709 int
1710 smb_fsop_lookup_name(
1711     smb_request_t *sr,
1712     cred_t      *cr,
1713     int         flags,
1714     smb_node_t  *root_node,
1715     smb_node_t  *dnode,
1716     char        *name,
1717     smb_node_t  **ret_snode)
1718 {
1719         smb_node_t      *fnode;
1720         vnode_t         *xattrdirvp;
1721         vnode_t         *vp;
1722         char            *od_name;
1723         char            *fname;
1724         char            *sname;
1725         int             rc;
1726 
1727         ASSERT(cr);
1728         ASSERT(dnode);
1729         ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
1730         ASSERT(dnode->n_state != SMB_NODE_STATE_DESTROYING);
1731 
1732         /*
1733          * The following check is required for streams processing, below
1734          */
1735 
1736         if (!(flags & SMB_CASE_SENSITIVE)) {
1737                 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1738                         flags |= SMB_IGNORE_CASE;
1739         }
1740 
1741         fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1742         sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1743 
1744         if (smb_is_stream_name(name)) {
1745                 smb_stream_parse_name(name, fname, sname);
1746 
1747                 /*
1748                  * Look up the unnamed stream (i.e. fname).
1749                  * Unmangle processing will be done on fname
1750                  * as well as any link target.
1751                  */
1752                 rc = smb_fsop_lookup(sr, cr, flags, root_node, dnode,
1753                     fname, &fnode);
1754 
1755                 if (rc != 0) {
1756                         kmem_free(fname, MAXNAMELEN);
1757                         kmem_free(sname, MAXNAMELEN);
1758                         return (rc);
1759                 }
1760 
1761                 od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1762 
1763                 /*
1764                  * od_name is the on-disk name of the stream, except
1765                  * without the prepended stream prefix (SMB_STREAM_PREFIX)
1766                  */
1767 
1768                 /*
1769                  * XXX
1770                  * What permissions NTFS requires for stream lookup if any?
1771                  */
1772                 rc = smb_vop_stream_lookup(fnode->vp, sname, &vp, od_name,
1773                     &xattrdirvp, flags, root_node->vp, cr);
1774 
1775                 if (rc != 0) {
1776                         smb_node_release(fnode);
1777                         kmem_free(fname, MAXNAMELEN);
1778                         kmem_free(sname, MAXNAMELEN);
1779                         kmem_free(od_name, MAXNAMELEN);
1780                         return (rc);
1781                 }
1782 
1783                 *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdirvp,
1784                     vp, od_name);
1785 
1786                 kmem_free(od_name, MAXNAMELEN);
1787                 smb_node_release(fnode);
1788                 VN_RELE(xattrdirvp);
1789                 VN_RELE(vp);
1790 
1791                 if (*ret_snode == NULL) {
1792                         kmem_free(fname, MAXNAMELEN);
1793                         kmem_free(sname, MAXNAMELEN);
1794                         return (ENOMEM);
1795                 }
1796         } else {
1797                 rc = smb_fsop_lookup(sr, cr, flags, root_node, dnode, name,
1798                     ret_snode);
1799         }
1800 
1801         if (rc == 0) {
1802                 ASSERT(ret_snode);
1803                 if (SMB_TREE_CONTAINS_NODE(sr, *ret_snode) == 0) {
1804                         smb_node_release(*ret_snode);
1805                         *ret_snode = NULL;
1806                         rc = EACCES;
1807                 }
1808         }
1809 
1810         kmem_free(fname, MAXNAMELEN);
1811         kmem_free(sname, MAXNAMELEN);
1812 
1813         return (rc);
1814 }
1815 
1816 /*
1817  * smb_fsop_lookup
1818  *
1819  * All SMB functions should use this smb_vop_lookup wrapper to ensure that
1820  * the smb_vop_lookup is performed with the appropriate credentials and using
1821  * case insensitive compares. Please document any direct call to smb_vop_lookup
1822  * to explain the reason for avoiding this wrapper.
1823  *
1824  * It is assumed that a reference exists on dnode coming into this routine
1825  * (and that it is safe from deallocation).
1826  *
1827  * Same with the root_node.
1828  *
1829  * *ret_snode is returned with a reference upon success.  No reference is
1830  * taken if an error is returned.
1831  *
1832  * Note: The returned ret_snode may be in a child mount.  This is ok for
 
1864         ASSERT(cr);
1865         ASSERT(dnode);
1866         ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
1867         ASSERT(dnode->n_state != SMB_NODE_STATE_DESTROYING);
1868 
1869         if (name == NULL)
1870                 return (EINVAL);
1871 
1872         if (SMB_TREE_CONTAINS_NODE(sr, dnode) == 0)
1873                 return (EACCES);
1874 
1875         if (!(flags & SMB_CASE_SENSITIVE)) {
1876                 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1877                         flags |= SMB_IGNORE_CASE;
1878         }
1879         if (SMB_TREE_SUPPORTS_CATIA(sr))
1880                 flags |= SMB_CATIA;
1881         if (SMB_TREE_SUPPORTS_ABE(sr))
1882                 flags |= SMB_ABE;
1883 
1884         od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1885 
1886         rc = smb_vop_lookup(dnode->vp, name, &vp, od_name, flags,
1887             &ret_flags, root_node ? root_node->vp : NULL, &attr, cr);
1888 
1889         if (rc != 0) {
1890                 if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
1891                     !smb_maybe_mangled(name)) {
1892                         kmem_free(od_name, MAXNAMELEN);
1893                         return (rc);
1894                 }
1895 
1896                 longname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1897                 rc = smb_unmangle(dnode, name, longname, MAXNAMELEN, flags);
1898                 if (rc != 0) {
1899                         kmem_free(od_name, MAXNAMELEN);
1900                         kmem_free(longname, MAXNAMELEN);
1901                         return (rc);
1902                 }
1903 
1904                 /*
1905                  * longname is the real (case-sensitive)
 
1910                  */
1911 
1912                 if (flags & SMB_IGNORE_CASE)
1913                         flags &= ~SMB_IGNORE_CASE;
1914 
1915                 rc = smb_vop_lookup(dnode->vp, longname, &vp, od_name,
1916                     flags, &ret_flags, root_node ? root_node->vp : NULL, &attr,
1917                     cr);
1918 
1919                 kmem_free(longname, MAXNAMELEN);
1920 
1921                 if (rc != 0) {
1922                         kmem_free(od_name, MAXNAMELEN);
1923                         return (rc);
1924                 }
1925         }
1926 
1927         if ((flags & SMB_FOLLOW_LINKS) && (vp->v_type == VLNK) &&
1928             ((attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)) {
1929                 rc = smb_pathname(sr, od_name, FOLLOW, root_node, dnode,
1930                     &lnk_dnode, &lnk_target_node, cr);
1931 
1932                 if (rc != 0) {
1933                         /*
1934                          * The link is assumed to be for the last component
1935                          * of a path.  Hence any ENOTDIR error will be returned
1936                          * as ENOENT.
1937                          */
1938                         if (rc == ENOTDIR)
1939                                 rc = ENOENT;
1940 
1941                         VN_RELE(vp);
1942                         kmem_free(od_name, MAXNAMELEN);
1943                         return (rc);
1944                 }
1945 
1946                 /*
1947                  * Release the original VLNK vnode
1948                  */
1949 
1950                 VN_RELE(vp);
 
2019  *
2020  * Retrieve filesystem ACL. Depends on requested ACLs in
2021  * fs_sd->sd_secinfo, it'll set DACL and SACL pointers in
2022  * fs_sd. Note that requesting a DACL/SACL doesn't mean that
2023  * the corresponding field in fs_sd should be non-NULL upon
2024  * return, since the target ACL might not contain that type of
2025  * entries.
2026  *
2027  * Returned ACL is always in ACE_T (aka ZFS) format.
2028  * If successful the allocated memory for the ACL should be freed
2029  * using smb_fsacl_free() or smb_fssd_term()
2030  */
2031 int
2032 smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2033     smb_fssd_t *fs_sd)
2034 {
2035         int error = 0;
2036         int flags = 0;
2037         int access = 0;
2038         acl_t *acl;
2039         smb_node_t *unnamed_node;
2040 
2041         ASSERT(cr);
2042 
2043         if (SMB_TREE_HAS_ACCESS(sr, ACE_READ_ACL) == 0)
2044                 return (EACCES);
2045 
2046         if (sr->fid_ofile) {
2047                 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2048                         access = READ_CONTROL;
2049 
2050                 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2051                         access |= ACCESS_SYSTEM_SECURITY;
2052 
2053                 error = smb_ofile_access(sr->fid_ofile, cr, access);
2054                 if (error != NT_STATUS_SUCCESS) {
2055                         return (EACCES);
2056                 }
2057         }
2058 
2059         unnamed_node = SMB_IS_STREAM(snode);
2060         if (unnamed_node) {
2061                 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
2062                 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
2063                 /*
2064                  * Streams don't have ACL, any read ACL attempt on a stream
2065                  * should be performed on the unnamed stream.
2066                  */
2067                 snode = unnamed_node;
2068         }
2069 
2070         if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_ACEMASKONACCESS))
2071                 flags = ATTR_NOACLCHECK;
2072 
2073         error = smb_vop_acl_read(snode->vp, &acl, flags,
2074             sr->tid_tree->t_acltype, cr);
2075         if (error != 0) {
2076                 return (error);
2077         }
2078 
2079         error = acl_translate(acl, _ACL_ACE_ENABLED,
2080             smb_node_is_dir(snode), fs_sd->sd_uid, fs_sd->sd_gid);
2081 
2082         if (error == 0) {
2083                 smb_fsacl_split(acl, &fs_sd->sd_zdacl, &fs_sd->sd_zsacl,
2084                     fs_sd->sd_secinfo);
2085         }
2086 
2087         acl_free(acl);
2088         return (error);
2089 }
2090 
2091 /*
2092  * smb_fsop_aclwrite
2093  *
2094  * Stores the filesystem ACL provided in fs_sd->sd_acl.
2095  */
2096 int
2097 smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2098     smb_fssd_t *fs_sd)
2099 {
2100         int target_flavor;
2101         int error = 0;
2102         int flags = 0;
2103         int access = 0;
2104         acl_t *acl, *dacl, *sacl;
2105         smb_node_t *unnamed_node;
2106 
2107         ASSERT(cr);
2108 
2109         ASSERT(sr);
2110         ASSERT(sr->tid_tree);
2111         if (SMB_TREE_IS_READONLY(sr))
2112                 return (EROFS);
2113 
2114         if (SMB_TREE_HAS_ACCESS(sr, ACE_WRITE_ACL) == 0)
2115                 return (EACCES);
2116 
2117         if (sr->fid_ofile) {
2118                 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2119                         access = WRITE_DAC;
2120 
2121                 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2122                         access |= ACCESS_SYSTEM_SECURITY;
2123 
2124                 error = smb_ofile_access(sr->fid_ofile, cr, access);
2125                 if (error != NT_STATUS_SUCCESS)
2126                         return (EACCES);
2127         }
2128 
2129         switch (sr->tid_tree->t_acltype) {
2130         case ACLENT_T:
2131                 target_flavor = _ACL_ACLENT_ENABLED;
2132                 break;
2133 
2134         case ACE_T:
2135                 target_flavor = _ACL_ACE_ENABLED;
2136                 break;
2137         default:
2138                 return (EINVAL);
2139         }
2140 
2141         unnamed_node = SMB_IS_STREAM(snode);
2142         if (unnamed_node) {
2143                 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
2144                 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
2145                 /*
2146                  * Streams don't have ACL, any write ACL attempt on a stream
2147                  * should be performed on the unnamed stream.
2148                  */
2149                 snode = unnamed_node;
2150         }
2151 
2152         dacl = fs_sd->sd_zdacl;
2153         sacl = fs_sd->sd_zsacl;
2154 
2155         ASSERT(dacl || sacl);
2156         if ((dacl == NULL) && (sacl == NULL))
2157                 return (EINVAL);
2158 
2159         if (dacl && sacl)
2160                 acl = smb_fsacl_merge(dacl, sacl);
2161         else if (dacl)
2162                 acl = dacl;
2163         else
2164                 acl = sacl;
2165 
2166         error = acl_translate(acl, target_flavor, smb_node_is_dir(snode),
2167             fs_sd->sd_uid, fs_sd->sd_gid);
2168         if (error == 0) {
2169                 if (smb_tree_has_feature(sr->tid_tree,
2170                     SMB_TREE_ACEMASKONACCESS))
2171                         flags = ATTR_NOACLCHECK;
 
2186 }
2187 
2188 /*
2189  * smb_fsop_sdread
2190  *
2191  * Read the requested security descriptor items from filesystem.
2192  * The items are specified in fs_sd->sd_secinfo.
2193  */
2194 int
2195 smb_fsop_sdread(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2196     smb_fssd_t *fs_sd)
2197 {
2198         int error = 0;
2199         int getowner = 0;
2200         cred_t *ga_cred;
2201         smb_attr_t attr;
2202 
2203         ASSERT(cr);
2204         ASSERT(fs_sd);
2205 
2206         /*
2207          * File's uid/gid is fetched in two cases:
2208          *
2209          * 1. it's explicitly requested
2210          *
2211          * 2. target ACL is ACE_T (ZFS ACL). They're needed for
2212          *    owner@/group@ entries. In this case kcred should be used
2213          *    because uid/gid are fetched on behalf of smb server.
2214          */
2215         if (fs_sd->sd_secinfo & (SMB_OWNER_SECINFO | SMB_GROUP_SECINFO)) {
2216                 getowner = 1;
2217                 ga_cred = cr;
2218         } else if (sr->tid_tree->t_acltype == ACE_T) {
2219                 getowner = 1;
2220                 ga_cred = zone_kcred();
2221         }
2222 
2223         if (getowner) {
2224                 /*
2225                  * Windows require READ_CONTROL to read owner/group SID since
 
2351  * in upper layers, so EPERM is mapped to EBADE.
2352  */
2353 int
2354 smb_fsop_sdwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2355     smb_fssd_t *fs_sd, int overwrite)
2356 {
2357         smb_attr_t set_attr;
2358         smb_attr_t orig_attr;
2359         cred_t *kcr = zone_kcred();
2360         int error = 0;
2361         int access = 0;
2362 
2363         ASSERT(cr);
2364         ASSERT(fs_sd);
2365 
2366         ASSERT(sr);
2367         ASSERT(sr->tid_tree);
2368         if (SMB_TREE_IS_READONLY(sr))
2369                 return (EROFS);
2370 
2371         bzero(&set_attr, sizeof (smb_attr_t));
2372 
2373         if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
2374                 set_attr.sa_vattr.va_uid = fs_sd->sd_uid;
2375                 set_attr.sa_mask |= SMB_AT_UID;
2376                 access |= WRITE_OWNER;
2377         }
2378 
2379         if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
2380                 set_attr.sa_vattr.va_gid = fs_sd->sd_gid;
2381                 set_attr.sa_mask |= SMB_AT_GID;
2382                 access |= WRITE_OWNER;
2383         }
2384 
2385         if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2386                 access |= WRITE_DAC;
2387 
2388         if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2389                 access |= ACCESS_SYSTEM_SECURITY;
2390 
 
2541                 return;
2542         }
2543 
2544         /*
2545          * FS doesn't understand 32-bit mask
2546          */
2547         smb_vop_eaccess(snode->vp, &access, 0, NULL, cr);
2548         access &= sr->tid_tree->t_access;
2549 
2550         *eaccess = READ_CONTROL | FILE_READ_EA | FILE_READ_ATTRIBUTES;
2551 
2552         if (access & VREAD)
2553                 *eaccess |= FILE_READ_DATA;
2554 
2555         if (access & VEXEC)
2556                 *eaccess |= FILE_EXECUTE;
2557 
2558         if (access & VWRITE)
2559                 *eaccess |= FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES |
2560                     FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD;
2561 }
2562 
2563 /*
2564  * smb_fsop_shrlock
2565  *
2566  * For the current open request, check file sharing rules
2567  * against existing opens.
2568  *
2569  * Returns NT_STATUS_SHARING_VIOLATION if there is any
2570  * sharing conflict.  Returns NT_STATUS_SUCCESS otherwise.
2571  *
2572  * Full system-wide share reservation synchronization is available
2573  * when the nbmand (non-blocking mandatory) mount option is set
2574  * (i.e. nbl_need_crit() is true) and nbmand critical regions are used.
2575  * This provides synchronization with NFS and local processes.  The
2576  * critical regions are entered in VOP_SHRLOCK()/fs_shrlock() (called
2577  * from smb_open_subr()/smb_fsop_shrlock()/smb_vop_shrlock()) as well
2578  * as the CIFS rename and delete paths.
2579  *
2580  * The CIFS server will also enter the nbl critical region in the open,
 
 
2621 {
2622         flock64_t bf;
2623         int flag = F_REMOTELOCK;
2624 
2625         /*
2626          * VOP_FRLOCK() will not be called if:
2627          *
2628          * 1) The lock has a range of zero bytes. The semantics of Windows and
2629          *    POSIX are different. In the case of POSIX it asks for the locking
2630          *    of all the bytes from the offset provided until the end of the
2631          *    file. In the case of Windows a range of zero locks nothing and
2632          *    doesn't conflict with any other lock.
2633          *
2634          * 2) The lock rolls over (start + lenght < start). Solaris will assert
2635          *    if such a request is submitted. This will not create
2636          *    incompatibilities between POSIX and Windows. In the Windows world,
2637          *    if a client submits such a lock, the server will not lock any
2638          *    bytes. Interestingly if the same lock (same offset and length) is
2639          *    resubmitted Windows will consider that there is an overlap and
2640          *    the granting rules will then apply.
2641          */
2642         if ((lock->l_length == 0) ||
2643             ((lock->l_start + lock->l_length - 1) < lock->l_start))
2644                 return (0);
2645 
2646         bzero(&bf, sizeof (bf));
2647 
2648         if (unlock) {
2649                 bf.l_type = F_UNLCK;
2650         } else if (lock->l_type == SMB_LOCK_TYPE_READONLY) {
2651                 bf.l_type = F_RDLCK;
2652                 flag |= FREAD;
2653         } else if (lock->l_type == SMB_LOCK_TYPE_READWRITE) {
2654                 bf.l_type = F_WRLCK;
2655                 flag |= FWRITE;
2656         }
2657 
2658         bf.l_start = lock->l_start;
2659         bf.l_len = lock->l_length;
2660         bf.l_pid = lock->l_file->f_uniqid;
 | 
 
 
   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 2018 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <sys/sid.h>
  27 #include <sys/nbmlock.h>
  28 #include <smbsrv/smb_fsops.h>
  29 #include <smbsrv/smb_kproto.h>
  30 #include <acl/acl_common.h>
  31 #include <sys/fcntl.h>
  32 #include <sys/filio.h>
  33 #include <sys/flock.h>
  34 #include <fs/fs_subr.h>
  35 
  36 extern caller_context_t smb_ct;
  37 
  38 static int smb_fsop_create_file_with_stream(smb_request_t *, cred_t *,
  39     smb_node_t *, char *, char *, int, smb_attr_t *, smb_node_t **);
  40 
  41 static int smb_fsop_create_file(smb_request_t *, cred_t *, smb_node_t *,
  42     char *, int, smb_attr_t *, smb_node_t **);
  43 
  44 #ifdef  _KERNEL
  45 static int smb_fsop_create_with_sd(smb_request_t *, cred_t *, smb_node_t *,
  46     char *, smb_attr_t *, smb_node_t **, smb_fssd_t *);
  47 static int smb_fsop_sdinherit(smb_request_t *, smb_node_t *, smb_fssd_t *);
  48 #endif  /* _KERNEL */
  49 
  50 /*
  51  * The smb_fsop_* functions have knowledge of CIFS semantics.
  52  *
  53  * The smb_vop_* functions have minimal knowledge of CIFS semantics and
  54  * serve as an interface to the VFS layer.
  55  *
  56  * Hence, smb_request_t and smb_node_t structures should not be passed
  57  * from the smb_fsop_* layer to the smb_vop_* layer.
  58  *
  59  * In general, CIFS service code should only ever call smb_fsop_*
 
 
 117 {
 118         smb_vop_close(node->vp, mode, cred);
 119 }
 120 
 121 #ifdef  _KERNEL
 122 static int
 123 smb_fsop_create_with_sd(smb_request_t *sr, cred_t *cr,
 124     smb_node_t *dnode, char *name,
 125     smb_attr_t *attr, smb_node_t **ret_snode, smb_fssd_t *fs_sd)
 126 {
 127         vsecattr_t *vsap;
 128         vsecattr_t vsecattr;
 129         smb_attr_t set_attr;
 130         acl_t *acl, *dacl, *sacl;
 131         vnode_t *vp;
 132         cred_t *kcr = zone_kcred();
 133         int aclbsize = 0;       /* size of acl list in bytes */
 134         int flags = 0;
 135         int rc;
 136         boolean_t is_dir;
 137         boolean_t do_audit;
 138 
 139         ASSERT(fs_sd);
 140         ASSERT(ret_snode != NULL);
 141 
 142         if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 143                 flags = SMB_IGNORE_CASE;
 144         if (SMB_TREE_SUPPORTS_CATIA(sr))
 145                 flags |= SMB_CATIA;
 146 
 147         ASSERT(cr);
 148 
 149         is_dir = ((fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) != 0);
 150 
 151         do_audit = smb_audit_init(sr);
 152         if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_ACLONCREATE)) {
 153                 if (fs_sd->sd_secinfo & SMB_ACL_SECINFO) {
 154                         dacl = fs_sd->sd_zdacl;
 155                         sacl = fs_sd->sd_zsacl;
 156                         ASSERT(dacl || sacl);
 157                         if (dacl && sacl) {
 158                                 acl = smb_fsacl_merge(dacl, sacl);
 159                         } else if (dacl) {
 160                                 acl = dacl;
 161                         } else {
 162                                 acl = sacl;
 163                         }
 164 
 165                         rc = smb_fsacl_to_vsa(acl, &vsecattr, &aclbsize);
 166 
 167                         if (dacl && sacl)
 168                                 acl_free(acl);
 169 
 170                         if (rc != 0)
 171                                 return (rc);
 172 
 173                         vsap = &vsecattr;
 174                 } else {
 175                         vsap = NULL;
 176                 }
 177 
 178                 /* The tree ACEs may prevent a create */
 179                 rc = EACCES;
 180                 if (is_dir) {
 181                         if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_SUBDIRECTORY) != 0)
 182                                 rc = smb_vop_mkdir(dnode->vp, name, attr,
 183                                     &vp, flags, cr, vsap);
 184                 } else {
 185                         if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_FILE) != 0)
 186                                 rc = smb_vop_create(dnode->vp, name, attr,
 187                                     &vp, flags, cr, vsap);
 188                 }
 189 
 190                 if (do_audit) {
 191                         smb_audit_fini(sr,
 192                             is_dir ? ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE,
 193                             dnode, rc == 0);
 194                 }
 195 
 196                 if (vsap != NULL)
 197                         kmem_free(vsap->vsa_aclentp, aclbsize);
 198 
 199                 if (rc != 0)
 200                         return (rc);
 201 
 202                 set_attr.sa_mask = 0;
 203 
 204                 /*
 205                  * Ideally we should be able to specify the owner and owning
 206                  * group at create time along with the ACL. Since we cannot
 207                  * do that right now, kcred is passed to smb_vop_setattr so it
 208                  * doesn't fail due to lack of permission.
 209                  */
 210                 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
 211                         set_attr.sa_vattr.va_uid = fs_sd->sd_uid;
 212                         set_attr.sa_mask |= SMB_AT_UID;
 213                 }
 214 
 215                 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
 
 230                         VN_RELE(vp);
 231                 }
 232         } else {
 233                 /*
 234                  * For filesystems that don't support ACL-on-create, try
 235                  * to set the specified SD after create, which could actually
 236                  * fail because of conflicts between inherited security
 237                  * attributes upon creation and the specified SD.
 238                  *
 239                  * Passing kcred to smb_fsop_sdwrite() to overcome this issue.
 240                  */
 241 
 242                 if (is_dir) {
 243                         rc = smb_vop_mkdir(dnode->vp, name, attr, &vp,
 244                             flags, cr, NULL);
 245                 } else {
 246                         rc = smb_vop_create(dnode->vp, name, attr, &vp,
 247                             flags, cr, NULL);
 248                 }
 249 
 250                 if (do_audit) {
 251                         smb_audit_fini(sr,
 252                             is_dir ? ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE,
 253                             dnode, rc == 0);
 254                 }
 255 
 256                 if (rc != 0)
 257                         return (rc);
 258 
 259                 *ret_snode = smb_node_lookup(sr, &sr->arg.open, cr, vp,
 260                     name, dnode, NULL);
 261 
 262                 if (*ret_snode != NULL) {
 263                         if (!smb_tree_has_feature(sr->tid_tree,
 264                             SMB_TREE_NFS_MOUNTED))
 265                                 rc = smb_fsop_sdwrite(sr, kcr, *ret_snode,
 266                                     fs_sd, 1);
 267                 } else {
 268                         rc = ENOMEM;
 269                 }
 270 
 271                 VN_RELE(vp);
 272         }
 273 
 274         if (rc != 0) {
 275                 if (is_dir)
 
 318         ASSERT(sr->tid_tree);
 319 
 320         if (SMB_TREE_CONTAINS_NODE(sr, dnode) == 0)
 321                 return (EACCES);
 322 
 323         if (SMB_TREE_IS_READONLY(sr))
 324                 return (EROFS);
 325 
 326         if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 327                 flags = SMB_IGNORE_CASE;
 328         if (SMB_TREE_SUPPORTS_CATIA(sr))
 329                 flags |= SMB_CATIA;
 330         if (SMB_TREE_SUPPORTS_ABE(sr))
 331                 flags |= SMB_ABE;
 332 
 333         if (smb_is_stream_name(name)) {
 334                 fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 335                 sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 336                 smb_stream_parse_name(name, fname, sname);
 337 
 338                 rc = smb_fsop_create_file_with_stream(sr, cr, dnode,
 339                     fname, sname, flags, attr, ret_snode);
 340 
 341                 kmem_free(fname, MAXNAMELEN);
 342                 kmem_free(sname, MAXNAMELEN);
 343                 return (rc);
 344         }
 345 
 346         /* Not a named stream */
 347 
 348         if (SMB_TREE_SUPPORTS_SHORTNAMES(sr) && smb_maybe_mangled(name)) {
 349                 longname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 350                 rc = smb_unmangle(dnode, name, longname, MAXNAMELEN, flags);
 351                 kmem_free(longname, MAXNAMELEN);
 352 
 353                 if (rc == 0)
 354                         rc = EEXIST;
 355                 if (rc != ENOENT)
 356                         return (rc);
 357         }
 358 
 359         rc = smb_fsop_create_file(sr, cr, dnode, name, flags,
 360             attr, ret_snode);
 361         return (rc);
 362 
 363 }
 364 
 365 
 366 /*
 367  * smb_fsop_create_file_with_stream
 368  *
 369  * Create named stream (sname) on file (fname), creating the file if it
 370  * doesn't exist.
 371  * If we created the file and then creation of the named stream fails,
 372  * we delete the file.
 373  * Since we use the real file name for the smb_vop_remove we
 374  * clear the SMB_IGNORE_CASE flag to ensure a case sensitive
 375  * match.
 376  *
 377  * Note that some stream "types" are "restricted" and only
 378  * internal callers (cr == kcred) can create those.
 379  */
 380 static int
 381 smb_fsop_create_file_with_stream(smb_request_t *sr, cred_t *cr,
 382     smb_node_t *dnode, char *fname, char *sname, int flags,
 383     smb_attr_t *attr, smb_node_t **ret_snode)
 384 {
 385         smb_node_t      *fnode;
 386         cred_t          *kcr = zone_kcred();
 387         int             rc = 0;
 388         boolean_t       fcreate = B_FALSE;
 389 
 390         ASSERT(ret_snode != NULL);
 391 
 392         if (cr != kcr && smb_strname_restricted(sname))
 393                 return (EACCES);
 394 
 395         /* Look up / create the unnamed stream, fname */
 396         rc = smb_fsop_lookup(sr, cr, flags | SMB_FOLLOW_LINKS,
 397             sr->tid_tree->t_snode, dnode, fname, &fnode);
 398         if (rc == ENOENT) {
 399                 fcreate = B_TRUE;
 400                 rc = smb_fsop_create_file(sr, cr, dnode, fname, flags,
 401                     attr, &fnode);
 402         }
 403         if (rc != 0)
 404                 return (rc);
 405 
 406         rc = smb_fsop_create_stream(sr, cr, dnode, fnode, sname, flags, attr,
 407             ret_snode);
 408 
 409         if (rc != 0) {
 410                 if (fcreate) {
 411                         flags &= ~SMB_IGNORE_CASE;
 412                         (void) smb_vop_remove(dnode->vp,
 413                             fnode->od_name, flags, cr);
 414                 }
 415         }
 416 
 417         smb_node_release(fnode);
 418         return (rc);
 419 }
 420 
 421 /*
 422  * smb_fsop_create_stream
 423  *
 424  * Create named stream (sname) on existing file (fnode).
 425  *
 426  * The second parameter of smb_vop_setattr() is set to
 427  * NULL, even though an unnamed stream exists.  This is
 428  * because we want to set the UID and GID on the named
 429  * stream in this case for consistency with the (unnamed
 430  * stream) file (see comments for smb_vop_setattr()).
 431  *
 432  * Note that some stream "types" are "restricted" and only
 433  * internal callers (cr == kcred) can create those.
 434  */
 435 int
 436 smb_fsop_create_stream(smb_request_t *sr, cred_t *cr,
 437     smb_node_t *dnode, smb_node_t *fnode, char *sname, int flags,
 438     smb_attr_t *attr, smb_node_t **ret_snode)
 439 {
 440         smb_attr_t      fattr;
 441         vnode_t         *xattrdvp;
 442         vnode_t         *vp;
 443         cred_t          *kcr = zone_kcred();
 444         int             rc = 0;
 445 
 446         ASSERT(ret_snode != NULL);
 447 
 448         if (cr != kcr && smb_strname_restricted(sname))
 449                 return (EACCES);
 450 
 451         bzero(&fattr, sizeof (fattr));
 452         fattr.sa_mask = SMB_AT_UID | SMB_AT_GID;
 453         rc = smb_vop_getattr(fnode->vp, NULL, &fattr, 0, kcr);
 454 
 455         if (rc == 0) {
 456                 /* create the named stream, sname */
 457                 rc = smb_vop_stream_create(fnode->vp, sname,
 458                     attr, &vp, &xattrdvp, flags, cr);
 459         }
 460         if (rc != 0)
 461                 return (rc);
 462 
 463         attr->sa_vattr.va_uid = fattr.sa_vattr.va_uid;
 464         attr->sa_vattr.va_gid = fattr.sa_vattr.va_gid;
 465         attr->sa_mask = SMB_AT_UID | SMB_AT_GID;
 466 
 467         rc = smb_vop_setattr(vp, NULL, attr, 0, kcr);
 468         if (rc != 0) {
 469                 VN_RELE(xattrdvp);
 470                 VN_RELE(vp);
 471                 return (rc);
 472         }
 473 
 474         *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdvp,
 475             vp, sname);
 476 
 477         VN_RELE(xattrdvp);
 478         VN_RELE(vp);
 479 
 480         if (*ret_snode == NULL)
 481                 rc = ENOMEM;
 482 
 483         /* notify change to the unnamed stream */
 484         if (rc == 0)
 485                 smb_node_notify_change(dnode,
 486                     FILE_ACTION_ADDED_STREAM, fnode->od_name);
 487 
 488         return (rc);
 489 }
 490 
 491 /*
 492  * smb_fsop_create_file
 493  */
 494 static int
 495 smb_fsop_create_file(smb_request_t *sr, cred_t *cr,
 496     smb_node_t *dnode, char *name, int flags,
 497     smb_attr_t *attr, smb_node_t **ret_snode)
 498 {
 499         smb_arg_open_t  *op = &sr->sr_open;
 500         vnode_t         *vp;
 501         int             rc;
 502 
 503         ASSERT(ret_snode != NULL);
 504 
 505 #ifdef  _KERNEL
 506         smb_fssd_t      fs_sd;
 507         uint32_t        secinfo;
 508         uint32_t        status;
 509 
 510         if (op->sd) {
 511                 /*
 512                  * SD sent by client in Windows format. Needs to be
 513                  * converted to FS format. No inheritance.
 514                  */
 515                 secinfo = smb_sd_get_secinfo(op->sd);
 516                 smb_fssd_init(&fs_sd, secinfo, 0);
 517 
 518                 status = smb_sd_tofs(op->sd, &fs_sd);
 519                 if (status == NT_STATUS_SUCCESS) {
 520                         rc = smb_fsop_create_with_sd(sr, cr, dnode,
 521                             name, attr, ret_snode, &fs_sd);
 522                 } else {
 523                         rc = EINVAL;
 524                 }
 
 526         } else if (sr->tid_tree->t_acltype == ACE_T) {
 527                 /*
 528                  * No incoming SD and filesystem is ZFS
 529                  * Server applies Windows inheritance rules,
 530                  * see smb_fsop_sdinherit() comments as to why.
 531                  */
 532                 smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, 0);
 533                 rc = smb_fsop_sdinherit(sr, dnode, &fs_sd);
 534                 if (rc == 0) {
 535                         rc = smb_fsop_create_with_sd(sr, cr, dnode,
 536                             name, attr, ret_snode, &fs_sd);
 537                 }
 538 
 539                 smb_fssd_term(&fs_sd);
 540         } else
 541 #endif  /* _KERNEL */
 542         {
 543                 /*
 544                  * No incoming SD and filesystem is not ZFS
 545                  * let the filesystem handles the inheritance.
 546                  *
 547                  * fsop_create_with_sd handles auditing in the other cases.
 548                  * Handle it explicitly here.
 549                  */
 550                 boolean_t do_audit = smb_audit_init(sr);
 551 
 552                 rc = smb_vop_create(dnode->vp, name, attr, &vp,
 553                     flags, cr, NULL);
 554 
 555                 if (do_audit) {
 556                         smb_audit_fini(sr, ACE_ADD_FILE, dnode, rc == 0);
 557                 }
 558 
 559                 if (rc == 0) {
 560                         *ret_snode = smb_node_lookup(sr, op, cr, vp,
 561                             name, dnode, NULL);
 562 
 563                         if (*ret_snode == NULL)
 564                                 rc = ENOMEM;
 565 
 566                         VN_RELE(vp);
 567                 }
 568 
 569         }
 570 
 571         if (rc == 0)
 572                 smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
 573 
 574         return (rc);
 575 }
 576 
 577 /*
 578  * smb_fsop_mkdir
 
 674                         rc = EINVAL;
 675                 smb_fssd_term(&fs_sd);
 676         } else if (sr->tid_tree->t_acltype == ACE_T) {
 677                 /*
 678                  * No incoming SD and filesystem is ZFS
 679                  * Server applies Windows inheritance rules,
 680                  * see smb_fsop_sdinherit() comments as to why.
 681                  */
 682                 smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, SMB_FSSD_FLAGS_DIR);
 683                 rc = smb_fsop_sdinherit(sr, dnode, &fs_sd);
 684                 if (rc == 0) {
 685                         rc = smb_fsop_create_with_sd(sr, cr, dnode,
 686                             name, attr, ret_snode, &fs_sd);
 687                 }
 688 
 689                 smb_fssd_term(&fs_sd);
 690 
 691         } else
 692 #endif  /* _KERNEL */
 693         {
 694                 /*
 695                  * fsop_create_with_sd handles auditing in the other cases.
 696                  * Handle it explicitly here.
 697                  */
 698                 boolean_t do_audit = smb_audit_init(sr);
 699 
 700                 rc = smb_vop_mkdir(dnode->vp, name, attr, &vp, flags, cr,
 701                     NULL);
 702 
 703                 if (do_audit) {
 704                         smb_audit_fini(sr, ACE_ADD_SUBDIRECTORY, dnode,
 705                             rc == 0);
 706                 }
 707 
 708                 if (rc == 0) {
 709                         *ret_snode = smb_node_lookup(sr, op, cr, vp, name,
 710                             dnode, NULL);
 711 
 712                         if (*ret_snode == NULL)
 713                                 rc = ENOMEM;
 714 
 715                         VN_RELE(vp);
 716                 }
 717         }
 718 
 719         if (rc == 0)
 720                 smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
 721 
 722         return (rc);
 723 }
 724 
 725 /*
 726  * smb_fsop_remove
 727  *
 728  * All SMB functions should use this wrapper to ensure that
 729  * the the calls are performed with the appropriate credentials.
 730  * Please document any direct call to explain the reason
 731  * for avoiding this wrapper.
 732  *
 733  * It is assumed that a reference exists on snode coming into this routine.
 734  *
 735  * A null smb_request might be passed to this function.
 736  *
 737  * Note that some stream "types" are "restricted" and only
 738  * internal callers (cr == kcred) can remove those.
 739  */
 740 int
 741 smb_fsop_remove(
 742     smb_request_t       *sr,
 743     cred_t              *cr,
 744     smb_node_t          *dnode,
 745     char                *name,
 746     uint32_t            flags)
 747 {
 748         smb_node_t      *fnode;
 749         char            *longname;
 750         char            *fname;
 751         char            *sname;
 752         int             rc;
 753 
 754         ASSERT(cr);
 755         /*
 756          * The state of the node could be SMB_NODE_STATE_DESTROYING if this
 757          * function is called during the deletion of the node (because of
 758          * DELETE_ON_CLOSE).
 759          */
 760         ASSERT(dnode);
 761         ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
 762 
 763         if (SMB_TREE_CONTAINS_NODE(sr, dnode) == 0 ||
 764             SMB_TREE_HAS_ACCESS(sr, ACE_DELETE) == 0)
 765                 return (EACCES);
 766 
 767         if (SMB_TREE_IS_READONLY(sr))
 768                 return (EROFS);
 769 
 770         fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 771         sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 772 
 773         if (dnode->flags & NODE_XATTR_DIR) {
 774                 if (cr != zone_kcred() && smb_strname_restricted(name)) {
 775                         rc = EACCES;
 776                         goto out;
 777                 }
 778 
 779                 fnode = dnode->n_dnode;
 780                 rc = smb_vop_stream_remove(fnode->vp, name, flags, cr);
 781 
 782                 /* notify change to the unnamed stream */
 783                 if ((rc == 0) && fnode->n_dnode) {
 784                         smb_node_notify_change(fnode->n_dnode,
 785                             FILE_ACTION_REMOVED_STREAM, fnode->od_name);
 786                 }
 787         } else if (smb_is_stream_name(name)) {
 788                 smb_stream_parse_name(name, fname, sname);
 789 
 790                 if (cr != zone_kcred() && smb_strname_restricted(sname)) {
 791                         rc = EACCES;
 792                         goto out;
 793                 }
 794 
 795                 /*
 796                  * Look up the unnamed stream (i.e. fname).
 797                  * Unmangle processing will be done on fname
 798                  * as well as any link target.
 799                  */
 800 
 801                 rc = smb_fsop_lookup(sr, cr, flags | SMB_FOLLOW_LINKS,
 802                     sr->tid_tree->t_snode, dnode, fname, &fnode);
 803 
 804                 if (rc != 0) {
 805                         goto out;
 806                 }
 807 
 808                 /*
 809                  * XXX
 810                  * Need to find out what permission is required by NTFS
 811                  * to remove a stream.
 812                  */
 813                 rc = smb_vop_stream_remove(fnode->vp, sname, flags, cr);
 814 
 815                 smb_node_release(fnode);
 816 
 817                 /* notify change to the unnamed stream */
 818                 if (rc == 0) {
 819                         smb_node_notify_change(dnode,
 820                             FILE_ACTION_REMOVED_STREAM, fname);
 821                 }
 822         } else {
 823                 rc = smb_vop_remove(dnode->vp, name, flags, cr);
 824 
 825                 if (rc == ENOENT) {
 826                         if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
 827                             !smb_maybe_mangled(name)) {
 828                                 goto out;
 829                         }
 830                         longname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 831 
 832                         if (SMB_TREE_SUPPORTS_ABE(sr))
 833                                 flags |= SMB_ABE;
 834 
 835                         rc = smb_unmangle(dnode, name, longname, MAXNAMELEN,
 836                             flags);
 837 
 838                         if (rc == 0) {
 839                                 /*
 840                                  * longname is the real (case-sensitive)
 841                                  * on-disk name.
 842                                  * We make sure we do a remove on this exact
 843                                  * name, as the name was mangled and denotes
 844                                  * a unique file.
 845                                  */
 846                                 flags &= ~SMB_IGNORE_CASE;
 847                                 rc = smb_vop_remove(dnode->vp, longname,
 848                                     flags, cr);
 849                         }
 850                         kmem_free(longname, MAXNAMELEN);
 851                 }
 852                 if (rc == 0) {
 853                         smb_node_notify_change(dnode,
 854                             FILE_ACTION_REMOVED, name);
 855                 }
 856         }
 857 
 858 out:
 859         kmem_free(fname, MAXNAMELEN);
 860         kmem_free(sname, MAXNAMELEN);
 861 
 862         return (rc);
 863 }
 864 
 865 /*
 866  * smb_fsop_remove_streams
 867  *
 868  * This function removes a file's streams without removing the
 869  * file itself.
 870  *
 871  * It is assumed that fnode is not a link.
 872  */
 873 uint32_t
 874 smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode)
 875 {
 876         int rc, flags = 0;
 877         smb_odir_t *od;
 878         smb_odirent_t *odirent;
 
 884         ASSERT(fnode);
 885         ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
 886         ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
 887 
 888         if (SMB_TREE_CONTAINS_NODE(sr, fnode) == 0)
 889                 return (NT_STATUS_ACCESS_DENIED);
 890 
 891         if (SMB_TREE_IS_READONLY(sr))
 892                 return (NT_STATUS_ACCESS_DENIED);
 893 
 894         if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 895                 flags = SMB_IGNORE_CASE;
 896 
 897         if (SMB_TREE_SUPPORTS_CATIA(sr))
 898                 flags |= SMB_CATIA;
 899 
 900         status = smb_odir_openat(sr, fnode, &od);
 901         switch (status) {
 902         case 0:
 903                 break;
 904         case NT_STATUS_OBJECT_NAME_NOT_FOUND:
 905         case NT_STATUS_NO_SUCH_FILE:
 906         case NT_STATUS_NOT_SUPPORTED:
 907                 /* No streams to remove. */
 908                 return (0);
 909         default:
 910                 return (status);
 911         }
 912 
 913         odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
 914         for (;;) {
 915                 rc = smb_odir_read(sr, od, odirent, &eos);
 916                 if ((rc != 0) || (eos))
 917                         break;
 918                 (void) smb_vop_remove(od->d_dnode->vp, odirent->od_name,
 919                     flags, cr);
 920         }
 921         kmem_free(odirent, sizeof (smb_odirent_t));
 922         if (eos && rc == ENOENT)
 923                 rc = 0;
 924 
 
1183         /*
1184          * Note: There is no need to check SMB_TREE_IS_CASEINSENSITIVE
1185          * here.
1186          *
1187          * A case-sensitive rename is always done in this routine
1188          * because we are using the on-disk name from an earlier lookup.
1189          * If a mangled name was passed in by the caller (denoting a
1190          * deterministic lookup), then the exact file must be renamed
1191          * (i.e. SMB_IGNORE_CASE must not be passed to VOP_RENAME, or
1192          * else the underlying file system might return a "first-match"
1193          * on this on-disk name, possibly resulting in the wrong file).
1194          */
1195 
1196         if (SMB_TREE_SUPPORTS_CATIA(sr))
1197                 flags |= SMB_CATIA;
1198 
1199         /*
1200          * XXX: Lock required through smb_node_release() below?
1201          */
1202 
1203         /*
1204          * Don't audit the lookup
1205          */
1206         smb_audit_save();
1207         rc = smb_vop_lookup(from_dnode->vp, from_name, &from_vp, NULL,
1208             flags, &ret_flags, NULL, &from_attr, cr);
1209         smb_audit_load();
1210 
1211         if (rc != 0)
1212                 return (rc);
1213 
1214         if (from_attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) {
1215                 VN_RELE(from_vp);
1216                 return (EACCES);
1217         }
1218 
1219         isdir = ((from_attr.sa_dosattr & FILE_ATTRIBUTE_DIRECTORY) != 0);
1220 
1221         if ((isdir && SMB_TREE_HAS_ACCESS(sr,
1222             ACE_DELETE_CHILD | ACE_ADD_SUBDIRECTORY) !=
1223             (ACE_DELETE_CHILD | ACE_ADD_SUBDIRECTORY)) ||
1224             (!isdir && SMB_TREE_HAS_ACCESS(sr, ACE_DELETE | ACE_ADD_FILE) !=
1225             (ACE_DELETE | ACE_ADD_FILE))) {
1226                 VN_RELE(from_vp);
1227                 return (EACCES);
1228         }
1229 
1230         /*
1231          * SMB checks access on open and retains an access granted
1232          * mask for use while the file is open.  ACL changes should
1233          * not affect access to an open file.
1234          *
1235          * If the rename is being performed on an ofile:
1236          * - Check the ofile's access granted mask to see if the
1237          *   rename is permitted - requires DELETE access.
1238          * - If the file system does access checking, set the
1239          *   ATTR_NOACLCHECK flag to ensure that the file system
1240          *   does not check permissions on subsequent calls.
1241          */
1242         if (sr && sr->fid_ofile) {
1243                 rc = smb_ofile_access(sr->fid_ofile, cr, DELETE);
1244                 if (rc != NT_STATUS_SUCCESS) {
1245                         VN_RELE(from_vp);
1246                         return (EACCES);
1247                 }
1248 
1249                 /* TODO: rename drops ATTR_NOACLCHECK, so this is a no-op. */
1250                 if (smb_tree_has_feature(sr->tid_tree,
1251                     SMB_TREE_ACEMASKONACCESS))
1252                         flags = ATTR_NOACLCHECK;
1253         }
1254 
1255         rc = smb_vop_rename(from_dnode->vp, from_name, to_dnode->vp,
1256             to_name, flags, cr);
1257 
1258         if (rc == 0) {
1259                 from_snode = smb_node_lookup(sr, NULL, cr, from_vp, from_name,
1260                     from_dnode, NULL);
1261 
1262                 if (from_snode == NULL) {
1263                         rc = ENOMEM;
1264                 } else {
1265                         smb_node_rename(from_dnode, from_snode,
1266                             to_dnode, to_name);
1267                         smb_node_release(from_snode);
1268                 }
1269         }
 
1314         int rc = 0;
1315         int flags = 0;
1316         uint_t sa_mask;
1317 
1318         ASSERT(cr);
1319         ASSERT(snode);
1320         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1321         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1322 
1323         if (SMB_TREE_CONTAINS_NODE(sr, snode) == 0)
1324                 return (EACCES);
1325 
1326         if (SMB_TREE_IS_READONLY(sr))
1327                 return (EROFS);
1328 
1329         if (SMB_TREE_HAS_ACCESS(sr,
1330             ACE_WRITE_ATTRIBUTES | ACE_WRITE_NAMED_ATTRS) == 0)
1331                 return (EACCES);
1332 
1333         /*
1334          * SMB checks access on open and retains an access granted
1335          * mask for use while the file is open.  ACL changes should
1336          * not affect access to an open file.
1337          *
1338          * If the setattr is being performed on an ofile:
1339          * - Check the ofile's access granted mask to see if the
1340          *   setattr is permitted.
1341          *   UID, GID - require WRITE_OWNER
1342          *   SIZE, ALLOCSZ - require FILE_WRITE_DATA
1343          *   all other attributes require FILE_WRITE_ATTRIBUTES
1344          *
1345          * - If the file system does access checking, set the
1346          *   ATTR_NOACLCHECK flag to ensure that the file system
1347          *   does not check permissions on subsequent calls.
1348          */
1349         if (sr && sr->fid_ofile) {
1350                 sa_mask = set_attr->sa_mask;
1351                 access = 0;
1352 
1353                 if (sa_mask & (SMB_AT_SIZE | SMB_AT_ALLOCSZ)) {
 
1369 
1370                 if (smb_tree_has_feature(sr->tid_tree,
1371                     SMB_TREE_ACEMASKONACCESS))
1372                         flags = ATTR_NOACLCHECK;
1373         }
1374 
1375         unnamed_node = SMB_IS_STREAM(snode);
1376 
1377         if (unnamed_node) {
1378                 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
1379                 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1380                 unnamed_vp = unnamed_node->vp;
1381         }
1382 
1383         rc = smb_vop_setattr(snode->vp, unnamed_vp, set_attr, flags, cr);
1384         return (rc);
1385 }
1386 
1387 /*
1388  * Support for SMB2 setinfo FileValidDataLengthInformation.
1389  * Free (zero out) data in the range off, off+len
1390  */
1391 int
1392 smb_fsop_freesp(
1393     smb_request_t       *sr,
1394     cred_t              *cr,
1395     smb_ofile_t         *ofile,
1396     off64_t             off,
1397     off64_t             len)
1398 {
1399         flock64_t flk;
1400         smb_node_t *node = ofile->f_node;
1401         uint32_t status;
1402         uint32_t access = FILE_WRITE_DATA;
1403         int rc;
1404 
1405         ASSERT(cr);
1406         ASSERT(node);
1407         ASSERT(node->n_magic == SMB_NODE_MAGIC);
1408         ASSERT(node->n_state != SMB_NODE_STATE_DESTROYING);
1409 
1410         if (SMB_TREE_CONTAINS_NODE(sr, node) == 0)
1411                 return (EACCES);
1412 
1413         if (SMB_TREE_IS_READONLY(sr))
1414                 return (EROFS);
1415 
1416         if (SMB_TREE_HAS_ACCESS(sr, access) == 0)
1417                 return (EACCES);
1418 
1419         /*
1420          * SMB checks access on open and retains an access granted
1421          * mask for use while the file is open.  ACL changes should
1422          * not affect access to an open file.
1423          *
1424          * If the setattr is being performed on an ofile:
1425          * - Check the ofile's access granted mask to see if this
1426          *   modification should be permitted (FILE_WRITE_DATA)
1427          */
1428         status = smb_ofile_access(sr->fid_ofile, cr, access);
1429         if (status != NT_STATUS_SUCCESS)
1430                 return (EACCES);
1431 
1432         bzero(&flk, sizeof (flk));
1433         flk.l_start = off;
1434         flk.l_len = len;
1435 
1436         rc = smb_vop_space(node->vp, F_FREESP, &flk, FWRITE, 0LL, cr);
1437         return (rc);
1438 }
1439 
1440 /*
1441  * smb_fsop_read
1442  *
1443  * All SMB functions should use this wrapper to ensure that
1444  * the the calls are performed with the appropriate credentials.
1445  * Please document any direct call to explain the reason
1446  * for avoiding this wrapper.
1447  *
1448  * It is assumed that a reference exists on snode coming into this routine.
1449  * Note that ofile may be different from sr->fid_ofile, or may be NULL.
1450  */
1451 int
1452 smb_fsop_read(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
1453     smb_ofile_t *ofile, uio_t *uio, int ioflag)
1454 {
1455         caller_context_t ct;
1456         cred_t *kcr = zone_kcred();
1457         uint32_t amask;
1458         int svmand;
1459         int rc;
1460 
1461         ASSERT(cr);
1462         ASSERT(snode);
1463         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1464         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1465 
1466         ASSERT(sr);
1467 
1468         if (ofile != NULL) {
1469                 /*
1470                  * Check tree access.  Not SMB_TREE_HAS_ACCESS
1471                  * because we need to use ofile->f_tree
1472                  */
1473                 if ((ofile->f_tree->t_access & ACE_READ_DATA) == 0)
1474                         return (EACCES);
1475 
1476                 /*
1477                  * Check ofile access.  Use in-line smb_ofile_access
1478                  * so we can check both amask bits at the same time.
1479                  * If any bit in amask is granted, allow this read.
1480                  */
1481                 amask = FILE_READ_DATA;
1482                 if (sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)
1483                         amask |= FILE_EXECUTE;
1484                 if (cr != kcr && (ofile->f_granted_access & amask) == 0)
1485                         return (EACCES);
1486         }
1487 
1488         /*
1489          * Streams permission are checked against the unnamed stream,
1490          * but in FS level they have their own permissions. To avoid
1491          * rejection by FS due to lack of permission on the actual
1492          * extended attr kcred is passed for streams.
1493          */
1494         if (SMB_IS_STREAM(snode))
1495                 cr = kcr;
1496 
1497         smb_node_start_crit(snode, RW_READER);
1498         rc = nbl_svmand(snode->vp, kcr, &svmand);
1499         if (rc) {
1500                 smb_node_end_crit(snode);
1501                 return (rc);
1502         }
1503 
1504         /*
1505          * Note: SMB allows a zero-byte read, which should not
1506          * conflict with any locks.  However nbl_lock_conflict
1507          * takes a zero-byte length as lock to EOF, so we must
1508          * special case that here.
1509          */
1510         if (uio->uio_resid > 0) {
1511                 ct = smb_ct;
1512                 if (ofile != NULL)
1513                         ct.cc_pid = ofile->f_uniqid;
1514                 rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset,
1515                     uio->uio_resid, svmand, &ct);
1516                 if (rc != 0) {
1517                         smb_node_end_crit(snode);
1518                         return (ERANGE);
1519                 }
1520         }
1521 
1522         rc = smb_vop_read(snode->vp, uio, ioflag, cr);
1523         smb_node_end_crit(snode);
1524 
1525         return (rc);
1526 }
1527 
1528 /*
1529  * smb_fsop_write
1530  *
1531  * It is assumed that a reference exists on snode coming into this routine.
1532  * Note that ofile may be different from sr->fid_ofile, or may be NULL.
1533  */
1534 int
1535 smb_fsop_write(
1536     smb_request_t *sr,
1537     cred_t *cr,
1538     smb_node_t *snode,
1539     smb_ofile_t *ofile,
1540     uio_t *uio,
1541     uint32_t *lcount,
1542     int ioflag)
1543 {
1544         caller_context_t ct;
1545         smb_attr_t attr;
1546         cred_t *kcr = zone_kcred();
1547         smb_node_t *u_node;
1548         vnode_t *u_vp = NULL;
1549         vnode_t *vp;
1550         uint32_t amask;
1551         int svmand;
1552         int rc;
1553 
1554         ASSERT(cr);
1555         ASSERT(snode);
1556         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1557         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1558 
1559         ASSERT(sr);
1560         vp = snode->vp;
1561 
1562         if (ofile != NULL) {
1563                 amask = FILE_WRITE_DATA | FILE_APPEND_DATA;
1564 
1565                 /* Check tree access. */
1566                 if ((ofile->f_tree->t_access & amask) == 0)
1567                         return (EROFS);
1568 
1569                 /*
1570                  * Check ofile access.  Use in-line smb_ofile_access
1571                  * so we can check both amask bits at the same time.
1572                  * If any bit in amask is granted, allow this write.
1573                  */
1574                 if (cr != kcr && (ofile->f_granted_access & amask) == 0)
1575                         return (EACCES);
1576         }
1577 
1578         /*
1579          * Streams permission are checked against the unnamed stream,
1580          * but in FS level they have their own permissions. To avoid
1581          * rejection by FS due to lack of permission on the actual
1582          * extended attr kcred is passed for streams.
1583          */
1584         u_node = SMB_IS_STREAM(snode);
1585         if (u_node != NULL) {
1586                 ASSERT(u_node->n_magic == SMB_NODE_MAGIC);
1587                 ASSERT(u_node->n_state != SMB_NODE_STATE_DESTROYING);
1588                 u_vp = u_node->vp;
1589                 cr = kcr;
1590         }
1591 
1592         smb_node_start_crit(snode, RW_WRITER);
1593         rc = nbl_svmand(vp, kcr, &svmand);
1594         if (rc) {
1595                 smb_node_end_crit(snode);
1596                 return (rc);
1597         }
1598 
1599         /*
1600          * Note: SMB allows a zero-byte write, which should not
1601          * conflict with any locks.  However nbl_lock_conflict
1602          * takes a zero-byte length as lock to EOF, so we must
1603          * special case that here.
1604          */
1605         if (uio->uio_resid > 0) {
1606                 ct = smb_ct;
1607                 if (ofile != NULL)
1608                         ct.cc_pid = ofile->f_uniqid;
1609                 rc = nbl_lock_conflict(vp, NBL_WRITE, uio->uio_loffset,
1610                     uio->uio_resid, svmand, &ct);
1611                 if (rc != 0) {
1612                         smb_node_end_crit(snode);
1613                         return (ERANGE);
1614                 }
1615         }
1616 
1617         rc = smb_vop_write(vp, uio, ioflag, lcount, cr);
1618 
1619         /*
1620          * Once the mtime has been set via this ofile, the
1621          * automatic mtime changes from writes via this ofile
1622          * should cease, preserving the mtime that was set.
1623          * See: [MS-FSA] 2.1.5.14 and smb_node_setattr.
1624          *
1625          * The VFS interface does not offer a way to ask it to
1626          * skip the mtime updates, so we simulate the desired
1627          * behavior by re-setting the mtime after writes on a
1628          * handle where the mtime has been set.
1629          */
1630         if (ofile != NULL &&
1631             (ofile->f_pending_attr.sa_mask & SMB_AT_MTIME) != 0) {
1632                 bcopy(&ofile->f_pending_attr, &attr, sizeof (attr));
1633                 attr.sa_mask = SMB_AT_MTIME;
1634                 (void) smb_vop_setattr(vp, u_vp, &attr, 0, kcr);
1635         }
1636 
1637         smb_node_end_crit(snode);
1638 
1639         return (rc);
1640 }
1641 
1642 /*
1643  * Find the next allocated range starting at or after
1644  * the offset (*datap), returning the start/end of
1645  * that range in (*datap, *holep)
1646  */
1647 int
1648 smb_fsop_next_alloc_range(
1649     cred_t *cr,
1650     smb_node_t *node,
1651     off64_t *datap,
1652     off64_t *holep)
1653 {
1654         int err;
1655 
1656         err = smb_vop_ioctl(node->vp, _FIO_SEEK_DATA, datap, cr);
1657         if (err != 0)
1658                 return (err);
1659 
1660         *holep = *datap;
1661         err = smb_vop_ioctl(node->vp, _FIO_SEEK_HOLE, holep, cr);
1662 
1663         return (err);
1664 }
1665 
1666 /*
1667  * smb_fsop_statfs
1668  *
1669  * This is a wrapper function used for stat operations.
1670  */
1671 int
1672 smb_fsop_statfs(
1673     cred_t *cr,
1674     smb_node_t *snode,
1675     struct statvfs64 *statp)
1676 {
1677         ASSERT(cr);
1678         ASSERT(snode);
1679         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1680         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1681 
1682         return (smb_vop_statfs(snode->vp, statp, cr));
1683 }
1684 
1685 /*
1686  * smb_fsop_access
1687  *
1688  * Named streams do not have separate permissions from the associated
1689  * unnamed stream.  Thus, if node is a named stream, the permissions
1690  * check will be performed on the associated unnamed stream.
1691  *
1692  * However, our named streams do have their own quarantine attribute,
1693  * separate from that on the unnamed stream. If READ or EXECUTE
1694  * access has been requested on a named stream, an additional access
1695  * check is performed on the named stream in case it has been
1696  * quarantined.  kcred is used to avoid issues with the permissions
1697  * set on the extended attribute file representing the named stream.
1698  *
1699  * Note that some stream "types" are "restricted" and only
1700  * internal callers (cr == kcred) can access those.
1701  */
1702 int
1703 smb_fsop_access(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
1704     uint32_t faccess)
1705 {
1706         int access = 0;
1707         int error;
1708         vnode_t *dir_vp;
1709         boolean_t acl_check = B_TRUE;
1710         smb_node_t *unnamed_node;
1711 
1712         ASSERT(sr);
1713         ASSERT(cr);
1714         ASSERT(snode);
1715         ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1716         ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1717 
1718         if (SMB_TREE_IS_READONLY(sr)) {
1719                 if (faccess & (FILE_WRITE_DATA|FILE_APPEND_DATA|
1720                     FILE_WRITE_EA|FILE_DELETE_CHILD|FILE_WRITE_ATTRIBUTES|
1721                     DELETE|WRITE_DAC|WRITE_OWNER)) {
1722                         return (NT_STATUS_ACCESS_DENIED);
1723                 }
1724         }
1725 
1726         if (smb_node_is_reparse(snode) && (faccess & DELETE))
1727                 return (NT_STATUS_ACCESS_DENIED);
1728 
1729         unnamed_node = SMB_IS_STREAM(snode);
1730         if (unnamed_node) {
1731                 cred_t *kcr = zone_kcred();
1732 
1733                 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
1734                 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1735 
1736                 if (cr != kcr && smb_strname_restricted(snode->od_name))
1737                         return (NT_STATUS_ACCESS_DENIED);
1738 
1739                 /*
1740                  * Perform VREAD access check on the named stream in case it
1741                  * is quarantined. kcred is passed to smb_vop_access so it
1742                  * doesn't fail due to lack of permission.
1743                  */
1744                 if (faccess & (FILE_READ_DATA | FILE_EXECUTE)) {
1745                         error = smb_vop_access(snode->vp, VREAD,
1746                             0, NULL, kcr);
1747                         if (error)
1748                                 return (NT_STATUS_ACCESS_DENIED);
1749                 }
1750 
1751                 /*
1752                  * Streams authorization should be performed against the
1753                  * unnamed stream.
1754                  */
1755                 snode = unnamed_node;
1756         }
1757 
1758         if (faccess & ACCESS_SYSTEM_SECURITY) {
1759                 /*
1760                  * This permission is required for reading/writing SACL and
1761                  * it's not part of DACL. It's only granted via proper
1762                  * privileges.
1763                  */
1764                 if ((sr->uid_user->u_privileges &
1765                     (SMB_USER_PRIV_BACKUP |
1766                     SMB_USER_PRIV_RESTORE |
 
1789                  * FS doesn't understand 32-bit mask, need to map
1790                  */
1791                 if (faccess & (FILE_WRITE_DATA | FILE_APPEND_DATA))
1792                         access |= VWRITE;
1793 
1794                 if (faccess & FILE_READ_DATA)
1795                         access |= VREAD;
1796 
1797                 if (faccess & FILE_EXECUTE)
1798                         access |= VEXEC;
1799 
1800                 error = smb_vop_access(snode->vp, access, 0, NULL, cr);
1801         }
1802 
1803         return ((error) ? NT_STATUS_ACCESS_DENIED : NT_STATUS_SUCCESS);
1804 }
1805 
1806 /*
1807  * smb_fsop_lookup_name()
1808  *
1809  * Lookup both the file and stream specified in 'name'.
1810  * If name indicates that the file is a stream file, perform
1811  * stream specific lookup, otherwise call smb_fsop_lookup.
1812  *
1813  * On success, returns the found node in *ret_snode. This will be either a named
1814  * or unnamed stream node, depending on the name specified.
1815  *
1816  * Return an error if the looked-up file is in outside the tree.
1817  * (Required when invoked from open path.)
1818  *
1819  * Case sensitivity flags (SMB_IGNORE_CASE, SMB_CASE_SENSITIVE):
1820  * if SMB_CASE_SENSITIVE is set, the SMB_IGNORE_CASE flag will NOT be set
1821  * based on the tree's case sensitivity. However, if the SMB_IGNORE_CASE
1822  * flag is set in the flags value passed as a parameter, a case insensitive
1823  * lookup WILL be done (regardless of whether SMB_CASE_SENSITIVE is set
1824  * or not).
1825  */
1826 
1827 int
1828 smb_fsop_lookup_name(
1829     smb_request_t *sr,
1830     cred_t      *cr,
1831     int         flags,
1832     smb_node_t  *root_node,
1833     smb_node_t  *dnode,
1834     char        *name,
1835     smb_node_t  **ret_snode)
1836 {
1837         char *sname = NULL;
1838         int rc;
1839         smb_node_t *tmp_node;
1840 
1841         ASSERT(ret_snode != NULL);
1842 
1843         rc = smb_fsop_lookup_file(sr, cr, flags, root_node, dnode, name,
1844             &sname, ret_snode);
1845 
1846         if (rc != 0 || sname == NULL)
1847                 return (rc);
1848 
1849         tmp_node = *ret_snode;
1850         rc = smb_fsop_lookup_stream(sr, cr, flags, root_node, tmp_node, sname,
1851             ret_snode);
1852         kmem_free(sname, MAXNAMELEN);
1853         smb_node_release(tmp_node);
1854 
1855         return (rc);
1856 }
1857 
1858 /*
1859  * smb_fsop_lookup_file()
1860  *
1861  * Look up of the file portion of 'name'. If a Stream is specified,
1862  * return the stream name in 'sname', which this allocates.
1863  * The caller must free 'sname'.
1864  *
1865  * Return an error if the looked-up file is outside the tree.
1866  * (Required when invoked from open path.)
1867  *
1868  * Case sensitivity flags (SMB_IGNORE_CASE, SMB_CASE_SENSITIVE):
1869  * if SMB_CASE_SENSITIVE is set, the SMB_IGNORE_CASE flag will NOT be set
1870  * based on the tree's case sensitivity. However, if the SMB_IGNORE_CASE
1871  * flag is set in the flags value passed as a parameter, a case insensitive
1872  * lookup WILL be done (regardless of whether SMB_CASE_SENSITIVE is set
1873  * or not).
1874  */
1875 
1876 int
1877 smb_fsop_lookup_file(
1878     smb_request_t *sr,
1879     cred_t      *cr,
1880     int         flags,
1881     smb_node_t  *root_node,
1882     smb_node_t  *dnode,
1883     char        *name,
1884     char        **sname,
1885     smb_node_t  **ret_snode)
1886 {
1887         char            *fname;
1888         int             rc;
1889 
1890         ASSERT(cr);
1891         ASSERT(dnode);
1892         ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
1893         ASSERT(dnode->n_state != SMB_NODE_STATE_DESTROYING);
1894         ASSERT(ret_snode != NULL);
1895 
1896         /*
1897          * The following check is required for streams processing, below
1898          */
1899 
1900         if (!(flags & SMB_CASE_SENSITIVE)) {
1901                 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1902                         flags |= SMB_IGNORE_CASE;
1903         }
1904 
1905         *sname = NULL;
1906         if (smb_is_stream_name(name)) {
1907                 *sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1908                 fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1909                 smb_stream_parse_name(name, fname, *sname);
1910 
1911                 /*
1912                  * Look up the unnamed stream (i.e. fname).
1913                  * Unmangle processing will be done on fname
1914                  * as well as any link target.
1915                  */
1916                 rc = smb_fsop_lookup(sr, cr, flags, root_node, dnode,
1917                     fname, ret_snode);
1918                 kmem_free(fname, MAXNAMELEN);
1919         } else {
1920                 rc = smb_fsop_lookup(sr, cr, flags, root_node, dnode, name,
1921                     ret_snode);
1922         }
1923 
1924         if (rc == 0) {
1925                 ASSERT(ret_snode);
1926                 if (SMB_TREE_CONTAINS_NODE(sr, *ret_snode) == 0) {
1927                         smb_node_release(*ret_snode);
1928                         *ret_snode = NULL;
1929                         rc = EACCES;
1930                 }
1931         }
1932 
1933         if (rc != 0 && *sname != NULL) {
1934                 kmem_free(*sname, MAXNAMELEN);
1935                 *sname = NULL;
1936         }
1937         return (rc);
1938 }
1939 
1940 /*
1941  * smb_fsop_lookup_stream
1942  *
1943  * The file exists, see if the stream exists.
1944  */
1945 int
1946 smb_fsop_lookup_stream(
1947     smb_request_t *sr,
1948     cred_t *cr,
1949     int flags,
1950     smb_node_t *root_node,
1951     smb_node_t *fnode,
1952     char *sname,
1953     smb_node_t **ret_snode)
1954 {
1955         char            *od_name;
1956         vnode_t         *xattrdirvp;
1957         vnode_t         *vp;
1958         int rc;
1959 
1960         /*
1961          * The following check is required for streams processing, below
1962          */
1963 
1964         if (!(flags & SMB_CASE_SENSITIVE)) {
1965                 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1966                         flags |= SMB_IGNORE_CASE;
1967         }
1968 
1969         od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1970 
1971         /*
1972          * od_name is the on-disk name of the stream, except
1973          * without the prepended stream prefix (SMB_STREAM_PREFIX)
1974          */
1975 
1976         rc = smb_vop_stream_lookup(fnode->vp, sname, &vp, od_name,
1977             &xattrdirvp, flags, root_node->vp, cr);
1978 
1979         if (rc != 0) {
1980                 kmem_free(od_name, MAXNAMELEN);
1981                 return (rc);
1982         }
1983 
1984         *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdirvp,
1985             vp, od_name);
1986 
1987         kmem_free(od_name, MAXNAMELEN);
1988         VN_RELE(xattrdirvp);
1989         VN_RELE(vp);
1990 
1991         if (*ret_snode == NULL)
1992                 return (ENOMEM);
1993 
1994         return (rc);
1995 }
1996 
1997 /*
1998  * smb_fsop_lookup
1999  *
2000  * All SMB functions should use this smb_vop_lookup wrapper to ensure that
2001  * the smb_vop_lookup is performed with the appropriate credentials and using
2002  * case insensitive compares. Please document any direct call to smb_vop_lookup
2003  * to explain the reason for avoiding this wrapper.
2004  *
2005  * It is assumed that a reference exists on dnode coming into this routine
2006  * (and that it is safe from deallocation).
2007  *
2008  * Same with the root_node.
2009  *
2010  * *ret_snode is returned with a reference upon success.  No reference is
2011  * taken if an error is returned.
2012  *
2013  * Note: The returned ret_snode may be in a child mount.  This is ok for
 
2045         ASSERT(cr);
2046         ASSERT(dnode);
2047         ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
2048         ASSERT(dnode->n_state != SMB_NODE_STATE_DESTROYING);
2049 
2050         if (name == NULL)
2051                 return (EINVAL);
2052 
2053         if (SMB_TREE_CONTAINS_NODE(sr, dnode) == 0)
2054                 return (EACCES);
2055 
2056         if (!(flags & SMB_CASE_SENSITIVE)) {
2057                 if (SMB_TREE_IS_CASEINSENSITIVE(sr))
2058                         flags |= SMB_IGNORE_CASE;
2059         }
2060         if (SMB_TREE_SUPPORTS_CATIA(sr))
2061                 flags |= SMB_CATIA;
2062         if (SMB_TREE_SUPPORTS_ABE(sr))
2063                 flags |= SMB_ABE;
2064 
2065         /*
2066          * Can have "" or "." when opening named streams on a directory.
2067          */
2068         if (name[0] == '\0' || (name[0] == '.' && name[1] == '\0')) {
2069                 smb_node_ref(dnode);
2070                 *ret_snode = dnode;
2071                 return (0);
2072         }
2073 
2074         od_name = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
2075 
2076         rc = smb_vop_lookup(dnode->vp, name, &vp, od_name, flags,
2077             &ret_flags, root_node ? root_node->vp : NULL, &attr, cr);
2078 
2079         if (rc != 0) {
2080                 if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
2081                     !smb_maybe_mangled(name)) {
2082                         kmem_free(od_name, MAXNAMELEN);
2083                         return (rc);
2084                 }
2085 
2086                 longname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
2087                 rc = smb_unmangle(dnode, name, longname, MAXNAMELEN, flags);
2088                 if (rc != 0) {
2089                         kmem_free(od_name, MAXNAMELEN);
2090                         kmem_free(longname, MAXNAMELEN);
2091                         return (rc);
2092                 }
2093 
2094                 /*
2095                  * longname is the real (case-sensitive)
 
2100                  */
2101 
2102                 if (flags & SMB_IGNORE_CASE)
2103                         flags &= ~SMB_IGNORE_CASE;
2104 
2105                 rc = smb_vop_lookup(dnode->vp, longname, &vp, od_name,
2106                     flags, &ret_flags, root_node ? root_node->vp : NULL, &attr,
2107                     cr);
2108 
2109                 kmem_free(longname, MAXNAMELEN);
2110 
2111                 if (rc != 0) {
2112                         kmem_free(od_name, MAXNAMELEN);
2113                         return (rc);
2114                 }
2115         }
2116 
2117         if ((flags & SMB_FOLLOW_LINKS) && (vp->v_type == VLNK) &&
2118             ((attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)) {
2119                 rc = smb_pathname(sr, od_name, FOLLOW, root_node, dnode,
2120                     &lnk_dnode, &lnk_target_node, cr, NULL);
2121 
2122                 if (rc != 0) {
2123                         /*
2124                          * The link is assumed to be for the last component
2125                          * of a path.  Hence any ENOTDIR error will be returned
2126                          * as ENOENT.
2127                          */
2128                         if (rc == ENOTDIR)
2129                                 rc = ENOENT;
2130 
2131                         VN_RELE(vp);
2132                         kmem_free(od_name, MAXNAMELEN);
2133                         return (rc);
2134                 }
2135 
2136                 /*
2137                  * Release the original VLNK vnode
2138                  */
2139 
2140                 VN_RELE(vp);
 
2209  *
2210  * Retrieve filesystem ACL. Depends on requested ACLs in
2211  * fs_sd->sd_secinfo, it'll set DACL and SACL pointers in
2212  * fs_sd. Note that requesting a DACL/SACL doesn't mean that
2213  * the corresponding field in fs_sd should be non-NULL upon
2214  * return, since the target ACL might not contain that type of
2215  * entries.
2216  *
2217  * Returned ACL is always in ACE_T (aka ZFS) format.
2218  * If successful the allocated memory for the ACL should be freed
2219  * using smb_fsacl_free() or smb_fssd_term()
2220  */
2221 int
2222 smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2223     smb_fssd_t *fs_sd)
2224 {
2225         int error = 0;
2226         int flags = 0;
2227         int access = 0;
2228         acl_t *acl;
2229 
2230         ASSERT(cr);
2231 
2232         /* Can't query security on named streams */
2233         if (SMB_IS_STREAM(snode) != NULL)
2234                 return (EINVAL);
2235 
2236         if (SMB_TREE_HAS_ACCESS(sr, ACE_READ_ACL) == 0)
2237                 return (EACCES);
2238 
2239         if (sr->fid_ofile) {
2240                 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2241                         access = READ_CONTROL;
2242 
2243                 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2244                         access |= ACCESS_SYSTEM_SECURITY;
2245 
2246                 error = smb_ofile_access(sr->fid_ofile, cr, access);
2247                 if (error != NT_STATUS_SUCCESS) {
2248                         return (EACCES);
2249                 }
2250         }
2251 
2252 
2253         if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_ACEMASKONACCESS))
2254                 flags = ATTR_NOACLCHECK;
2255 
2256         error = smb_vop_acl_read(snode->vp, &acl, flags,
2257             sr->tid_tree->t_acltype, cr);
2258         if (error != 0) {
2259                 return (error);
2260         }
2261 
2262         error = acl_translate(acl, _ACL_ACE_ENABLED,
2263             smb_node_is_dir(snode), fs_sd->sd_uid, fs_sd->sd_gid);
2264 
2265         if (error == 0) {
2266                 smb_fsacl_split(acl, &fs_sd->sd_zdacl, &fs_sd->sd_zsacl,
2267                     fs_sd->sd_secinfo);
2268         }
2269 
2270         acl_free(acl);
2271         return (error);
2272 }
2273 
2274 /*
2275  * smb_fsop_aclwrite
2276  *
2277  * Stores the filesystem ACL provided in fs_sd->sd_acl.
2278  */
2279 int
2280 smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2281     smb_fssd_t *fs_sd)
2282 {
2283         int target_flavor;
2284         int error = 0;
2285         int flags = 0;
2286         int access = 0;
2287         acl_t *acl, *dacl, *sacl;
2288 
2289         ASSERT(cr);
2290 
2291         ASSERT(sr);
2292         ASSERT(sr->tid_tree);
2293         if (SMB_TREE_IS_READONLY(sr))
2294                 return (EROFS);
2295 
2296         /* Can't set security on named streams */
2297         if (SMB_IS_STREAM(snode) != NULL)
2298                 return (EINVAL);
2299 
2300         if (SMB_TREE_HAS_ACCESS(sr, ACE_WRITE_ACL) == 0)
2301                 return (EACCES);
2302 
2303         if (sr->fid_ofile) {
2304                 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2305                         access = WRITE_DAC;
2306 
2307                 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2308                         access |= ACCESS_SYSTEM_SECURITY;
2309 
2310                 error = smb_ofile_access(sr->fid_ofile, cr, access);
2311                 if (error != NT_STATUS_SUCCESS)
2312                         return (EACCES);
2313         }
2314 
2315         switch (sr->tid_tree->t_acltype) {
2316         case ACLENT_T:
2317                 target_flavor = _ACL_ACLENT_ENABLED;
2318                 break;
2319 
2320         case ACE_T:
2321                 target_flavor = _ACL_ACE_ENABLED;
2322                 break;
2323         default:
2324                 return (EINVAL);
2325         }
2326 
2327         dacl = fs_sd->sd_zdacl;
2328         sacl = fs_sd->sd_zsacl;
2329 
2330         ASSERT(dacl || sacl);
2331         if ((dacl == NULL) && (sacl == NULL))
2332                 return (EINVAL);
2333 
2334         if (dacl && sacl)
2335                 acl = smb_fsacl_merge(dacl, sacl);
2336         else if (dacl)
2337                 acl = dacl;
2338         else
2339                 acl = sacl;
2340 
2341         error = acl_translate(acl, target_flavor, smb_node_is_dir(snode),
2342             fs_sd->sd_uid, fs_sd->sd_gid);
2343         if (error == 0) {
2344                 if (smb_tree_has_feature(sr->tid_tree,
2345                     SMB_TREE_ACEMASKONACCESS))
2346                         flags = ATTR_NOACLCHECK;
 
2361 }
2362 
2363 /*
2364  * smb_fsop_sdread
2365  *
2366  * Read the requested security descriptor items from filesystem.
2367  * The items are specified in fs_sd->sd_secinfo.
2368  */
2369 int
2370 smb_fsop_sdread(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2371     smb_fssd_t *fs_sd)
2372 {
2373         int error = 0;
2374         int getowner = 0;
2375         cred_t *ga_cred;
2376         smb_attr_t attr;
2377 
2378         ASSERT(cr);
2379         ASSERT(fs_sd);
2380 
2381         /* Can't query security on named streams */
2382         if (SMB_IS_STREAM(snode) != NULL)
2383                 return (EINVAL);
2384 
2385         /*
2386          * File's uid/gid is fetched in two cases:
2387          *
2388          * 1. it's explicitly requested
2389          *
2390          * 2. target ACL is ACE_T (ZFS ACL). They're needed for
2391          *    owner@/group@ entries. In this case kcred should be used
2392          *    because uid/gid are fetched on behalf of smb server.
2393          */
2394         if (fs_sd->sd_secinfo & (SMB_OWNER_SECINFO | SMB_GROUP_SECINFO)) {
2395                 getowner = 1;
2396                 ga_cred = cr;
2397         } else if (sr->tid_tree->t_acltype == ACE_T) {
2398                 getowner = 1;
2399                 ga_cred = zone_kcred();
2400         }
2401 
2402         if (getowner) {
2403                 /*
2404                  * Windows require READ_CONTROL to read owner/group SID since
 
2530  * in upper layers, so EPERM is mapped to EBADE.
2531  */
2532 int
2533 smb_fsop_sdwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2534     smb_fssd_t *fs_sd, int overwrite)
2535 {
2536         smb_attr_t set_attr;
2537         smb_attr_t orig_attr;
2538         cred_t *kcr = zone_kcred();
2539         int error = 0;
2540         int access = 0;
2541 
2542         ASSERT(cr);
2543         ASSERT(fs_sd);
2544 
2545         ASSERT(sr);
2546         ASSERT(sr->tid_tree);
2547         if (SMB_TREE_IS_READONLY(sr))
2548                 return (EROFS);
2549 
2550         /* Can't set security on named streams */
2551         if (SMB_IS_STREAM(snode) != NULL)
2552                 return (EINVAL);
2553 
2554         bzero(&set_attr, sizeof (smb_attr_t));
2555 
2556         if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
2557                 set_attr.sa_vattr.va_uid = fs_sd->sd_uid;
2558                 set_attr.sa_mask |= SMB_AT_UID;
2559                 access |= WRITE_OWNER;
2560         }
2561 
2562         if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
2563                 set_attr.sa_vattr.va_gid = fs_sd->sd_gid;
2564                 set_attr.sa_mask |= SMB_AT_GID;
2565                 access |= WRITE_OWNER;
2566         }
2567 
2568         if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2569                 access |= WRITE_DAC;
2570 
2571         if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2572                 access |= ACCESS_SYSTEM_SECURITY;
2573 
 
2724                 return;
2725         }
2726 
2727         /*
2728          * FS doesn't understand 32-bit mask
2729          */
2730         smb_vop_eaccess(snode->vp, &access, 0, NULL, cr);
2731         access &= sr->tid_tree->t_access;
2732 
2733         *eaccess = READ_CONTROL | FILE_READ_EA | FILE_READ_ATTRIBUTES;
2734 
2735         if (access & VREAD)
2736                 *eaccess |= FILE_READ_DATA;
2737 
2738         if (access & VEXEC)
2739                 *eaccess |= FILE_EXECUTE;
2740 
2741         if (access & VWRITE)
2742                 *eaccess |= FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES |
2743                     FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD;
2744 
2745         if (access & (VREAD | VWRITE))
2746                 *eaccess |= SYNCHRONIZE;
2747 
2748 #ifdef  _FAKE_KERNEL
2749         /* Should be: if (we are the owner)... */
2750         if (access & VWRITE)
2751                 *eaccess |= DELETE | WRITE_DAC | WRITE_OWNER;
2752 #endif
2753 }
2754 
2755 /*
2756  * smb_fsop_shrlock
2757  *
2758  * For the current open request, check file sharing rules
2759  * against existing opens.
2760  *
2761  * Returns NT_STATUS_SHARING_VIOLATION if there is any
2762  * sharing conflict.  Returns NT_STATUS_SUCCESS otherwise.
2763  *
2764  * Full system-wide share reservation synchronization is available
2765  * when the nbmand (non-blocking mandatory) mount option is set
2766  * (i.e. nbl_need_crit() is true) and nbmand critical regions are used.
2767  * This provides synchronization with NFS and local processes.  The
2768  * critical regions are entered in VOP_SHRLOCK()/fs_shrlock() (called
2769  * from smb_open_subr()/smb_fsop_shrlock()/smb_vop_shrlock()) as well
2770  * as the CIFS rename and delete paths.
2771  *
2772  * The CIFS server will also enter the nbl critical region in the open,
 
 
2813 {
2814         flock64_t bf;
2815         int flag = F_REMOTELOCK;
2816 
2817         /*
2818          * VOP_FRLOCK() will not be called if:
2819          *
2820          * 1) The lock has a range of zero bytes. The semantics of Windows and
2821          *    POSIX are different. In the case of POSIX it asks for the locking
2822          *    of all the bytes from the offset provided until the end of the
2823          *    file. In the case of Windows a range of zero locks nothing and
2824          *    doesn't conflict with any other lock.
2825          *
2826          * 2) The lock rolls over (start + lenght < start). Solaris will assert
2827          *    if such a request is submitted. This will not create
2828          *    incompatibilities between POSIX and Windows. In the Windows world,
2829          *    if a client submits such a lock, the server will not lock any
2830          *    bytes. Interestingly if the same lock (same offset and length) is
2831          *    resubmitted Windows will consider that there is an overlap and
2832          *    the granting rules will then apply.
2833          *
2834          * 3) The SMB-level process IDs (smb_pid) are not passed down to the
2835          *    POSIX level in l_pid because (a) the rules about lock PIDs are
2836          *    different in SMB, and (b) we're putting our ofile f_uniqid in
2837          *    the POSIX l_pid field to segregate locks per SMB ofile.
2838          *    (We're also using a "remote" system ID in l_sysid.)
2839          *    All SMB locking PIDs are handled at the SMB level and
2840          *    not exposed in POSIX locking.
2841          */
2842         if ((lock->l_length == 0) ||
2843             ((lock->l_start + lock->l_length - 1) < lock->l_start))
2844                 return (0);
2845 
2846         bzero(&bf, sizeof (bf));
2847 
2848         if (unlock) {
2849                 bf.l_type = F_UNLCK;
2850         } else if (lock->l_type == SMB_LOCK_TYPE_READONLY) {
2851                 bf.l_type = F_RDLCK;
2852                 flag |= FREAD;
2853         } else if (lock->l_type == SMB_LOCK_TYPE_READWRITE) {
2854                 bf.l_type = F_WRLCK;
2855                 flag |= FWRITE;
2856         }
2857 
2858         bf.l_start = lock->l_start;
2859         bf.l_len = lock->l_length;
2860         bf.l_pid = lock->l_file->f_uniqid;
 |