1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  27  */
  28 
  29 /*
  30  * ACL support for smbfs
  31  */
  32 
  33 #include <sys/systm.h>    /* bcopy, ... */
  34 #include <sys/errno.h>
  35 #include <sys/cred.h>
  36 #include <sys/cmn_err.h>
  37 #include <sys/kmem.h>
  38 #include <sys/sunddi.h>
  39 #include <sys/acl.h>
  40 #include <sys/vnode.h>
  41 #include <sys/vfs.h>
  42 #include <sys/byteorder.h>
  43 
  44 #include <netsmb/mchain.h>
  45 #include <netsmb/smb.h>
  46 #include <netsmb/smb_conn.h>
  47 #include <netsmb/smb_osdep.h>
  48 #include <netsmb/smb_subr.h>
  49 
  50 #include <smbfs/smbfs.h>
  51 #include <smbfs/smbfs_node.h>
  52 #include <smbfs/smbfs_subr.h>
  53 
  54 #include <sys/fs/smbfs_ioctl.h>
  55 #include <fs/fs_subr.h>
  56 #include "smbfs_ntacl.h"
  57 
  58 /* Sanity check SD sizes */
  59 #define MAX_RAW_SD_SIZE 32768
  60 #define SMALL_SD_SIZE   1024
  61 
  62 /*
  63  * smbfs_getsd() is a common function used by both
  64  * smbfs_ioctl SMBFSIO_GETSD and VOP_GETSECATTR.
  65  * Handles required rights, tmpopen/tmpclose.
  66  *
  67  * Note: smbfs_getsd allocates and returns an mblk chain,
  68  * which the caller must free.
  69  */
  70 static int
  71 smbfs_getsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr)
  72 {
  73         struct smb_cred scred;
  74         smbmntinfo_t *smi;
  75         smbnode_t       *np;
  76         smb_fh_t        *fid = NULL;
  77         uint32_t        sdlen = SMALL_SD_SIZE;
  78         uint32_t        rights = STD_RIGHT_READ_CONTROL_ACCESS;
  79         int error;
  80 
  81         if (selector & SACL_SECURITY_INFORMATION)
  82                 rights |= SEC_RIGHT_SYSTEM_SECURITY;
  83 
  84         np = VTOSMB(vp);
  85         smi = VTOSMI(vp);
  86 
  87         smb_credinit(&scred, cr);
  88 
  89         error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
  90         if (error)
  91                 goto out;
  92 
  93 again:
  94         /*
  95          * This does the OTW Get
  96          */
  97         error = smbfs_smb_getsec(smi->smi_share, fid,
  98             selector, mp, &sdlen, &scred);
  99         /*
 100          * Server may give us an error indicating that we
 101          * need a larger data buffer to receive the SD,
 102          * and the size we'll need.  Use the given size,
 103          * but only after a sanity check.
 104          *
 105          * Let's check for specific error values here.
 106          * The NT error is: STATUS_BUFFER_TOO_SMALL,
 107          * or with old error codes, one of these:
 108          * ERRSRV/ERRnoroom, ERRDOS/122, ERRDOS/111
 109          * Those are mapped to: EMOREDATA, which is
 110          * later converted to E2BIG.
 111          */
 112         if (error == E2BIG &&
 113             sdlen > SMALL_SD_SIZE &&
 114             sdlen <= MAX_RAW_SD_SIZE)
 115                 goto again;
 116 
 117         smbfs_smb_tmpclose(np, fid);
 118 
 119 out:
 120         smb_credrele(&scred);
 121 
 122         return (error);
 123 }
 124 
 125 /*
 126  * smbfs_setsd() is a common function used by both
 127  * smbfs_ioctl SMBFSIO_SETSD and VOP_SETSECATTR.
 128  * Handles required rights, tmpopen/tmpclose.
 129  *
 130  * Note: smbfs_setsd _consumes_ the passed *mp and
 131  * clears the pointer (so the caller won't free it)
 132  */
 133 static int
 134 smbfs_setsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr)
 135 {
 136         struct smb_cred scred;
 137         smbmntinfo_t *smi;
 138         smbnode_t       *np;
 139         uint32_t        rights;
 140         smb_fh_t        *fid = NULL;
 141         int error;
 142 
 143         np = VTOSMB(vp);
 144         smi = VTOSMI(vp);
 145 
 146         /*
 147          * Which parts of the SD are we setting?
 148          * What rights do we need for that?
 149          */
 150         if (selector == 0)
 151                 return (0);
 152 
 153         rights = 0;
 154         if (selector & (OWNER_SECURITY_INFORMATION |
 155             GROUP_SECURITY_INFORMATION))
 156                 rights |= STD_RIGHT_WRITE_OWNER_ACCESS;
 157         if (selector & DACL_SECURITY_INFORMATION)
 158                 rights |= STD_RIGHT_WRITE_DAC_ACCESS;
 159         if (selector & SACL_SECURITY_INFORMATION)
 160                 rights |= SEC_RIGHT_SYSTEM_SECURITY;
 161 
 162         smb_credinit(&scred, cr);
 163 
 164         error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
 165         if (error)
 166                 goto out;
 167 
 168         /*
 169          * We're setting the remote ACL now, so
 170          * invalidate our cached ACL just in case
 171          * the server doesn't do exactly as we ask.
 172          */
 173         mutex_enter(&np->r_statelock);
 174         np->r_sectime = gethrtime();
 175         mutex_exit(&np->r_statelock);
 176 
 177         /*
 178          * This does the OTW Set
 179          */
 180         error = smbfs_smb_setsec(smi->smi_share, fid,
 181             selector, mp, &scred);
 182 
 183         smbfs_smb_tmpclose(np, fid);
 184 
 185 out:
 186         smb_credrele(&scred);
 187 
 188         return (error);
 189 }
 190 
 191 /*
 192  * Helper for VOP_IOCTL: SMBFSIO_GETSD
 193  */
 194 int
 195 smbfs_acl_iocget(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
 196 {
 197         ioc_sdbuf_t iocb;
 198         mdchain_t *mdp, md_store;
 199         mblk_t *m;
 200         void *ubuf;
 201         int error;
 202 
 203         /*
 204          * Get the buffer information
 205          */
 206         if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag))
 207                 return (EFAULT);
 208 
 209         /*
 210          * This does the OTW Get (and maybe open, close)
 211          * Allocates and returns an mblk in &m.
 212          */
 213         error = smbfs_getsd(vp, iocb.selector, &m, cr);
 214         if (error)
 215                 return (error);
 216 
 217         /*
 218          * Have m.  Must free it before return.
 219          */
 220         mdp = &md_store;
 221         md_initm(mdp, m);
 222         iocb.used = m_fixhdr(m);
 223 
 224         /*
 225          * Always copyout the buffer information,
 226          * so the user can realloc and try again
 227          * after an EOVERFLOW return.
 228          */
 229         if (ddi_copyout(&iocb, (void *)arg, sizeof (iocb), flag)) {
 230                 error = EFAULT;
 231                 goto out;
 232         }
 233 
 234         if (iocb.used > iocb.alloc) {
 235                 error = EOVERFLOW;
 236                 goto out;
 237         }
 238 
 239         /*
 240          * Copyout the buffer contents (SD)
 241          */
 242         ubuf = (void *)(uintptr_t)iocb.addr;
 243         error = md_get_mem(mdp, ubuf, iocb.used, MB_MUSER);
 244 
 245 out:
 246         /* Note: m_freem(m) is done by... */
 247         md_done(mdp);
 248 
 249         return (error);
 250 }
 251 
 252 /*
 253  * Helper for VOP_IOCTL: SMBFSIO_SETSD
 254  */
 255 int
 256 smbfs_acl_iocset(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
 257 {
 258         ioc_sdbuf_t iocb;
 259         mbchain_t *mbp, mb_store;
 260         void *ubuf;
 261         int error;
 262 
 263         /*
 264          * Get the buffer information
 265          */
 266         if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag))
 267                 return (EFAULT);
 268 
 269         if (iocb.used < sizeof (ntsecdesc_t) ||
 270             iocb.used >= MAX_RAW_SD_SIZE)
 271                 return (EINVAL);
 272 
 273         /*
 274          * Get the buffer contents (security descriptor data)
 275          */
 276         mbp = &mb_store;
 277         (void) mb_init(mbp);
 278         ubuf = (void *)(uintptr_t)iocb.addr;
 279         error = mb_put_mem(mbp, ubuf, iocb.used, MB_MUSER);
 280         if (error)
 281                 goto out;
 282 
 283         /*
 284          * This does the OTW Set (and maybe open, close)
 285          * It clears mb_top when consuming the message.
 286          */
 287         error = smbfs_setsd(vp, iocb.selector, &mbp->mb_top, cr);
 288 
 289 out:
 290         mb_done(mbp);
 291         return (error);
 292 
 293 }
 294 
 295 /*
 296  * Refresh our cached copy of the security attributes
 297  */
 298 static int
 299 smbfs_acl_refresh(vnode_t *vp, cred_t *cr)
 300 {
 301         smbnode_t *np;
 302         smbmntinfo_t *smi;
 303         mdchain_t *mdp, md_store;
 304         mblk_t *m = NULL;
 305         i_ntsd_t *sd = NULL;
 306         vsecattr_t vsa, ovsa;
 307         uint32_t selector;
 308         uid_t uid;
 309         gid_t gid;
 310         int error;
 311 
 312         np = VTOSMB(vp);
 313         smi = VTOSMI(vp);
 314 
 315         bzero(&md_store, sizeof (md_store));
 316         mdp = &md_store;
 317 
 318         /*
 319          * Which parts of the SD we request.
 320          * Not getting the SACL for now.
 321          */
 322         selector = DACL_SECURITY_INFORMATION |
 323             OWNER_SECURITY_INFORMATION |
 324             GROUP_SECURITY_INFORMATION;
 325 
 326         /*
 327          * This does the OTW Get (and maybe open, close)
 328          * Allocates and returns an mblk in &m.
 329          */
 330         error = smbfs_getsd(vp, selector, &m, cr);
 331         if (error)
 332                 goto out;
 333         /* Note: allocated *m */
 334         md_initm(mdp, m);
 335 
 336         /*
 337          * Parse the OtW security descriptor,
 338          * storing in our internal form.
 339          */
 340         error = md_get_ntsd(mdp, &sd);
 341         if (error)
 342                 goto out;
 343 
 344         /*
 345          * Convert the Windows security descriptor to a
 346          * ZFS ACL (and owner ID, primary group ID).
 347          */
 348         bzero(&vsa, sizeof (vsa));
 349         vsa.vsa_mask = VSA_ACE | VSA_ACECNT;
 350         error = smbfs_acl_sd2zfs(sd, &vsa, &uid, &gid);
 351         if (error)
 352                 goto out;
 353 
 354         ASSERT(vsa.vsa_aclentp != NULL);
 355         SMBVDEBUG("uid=%u, gid=%u", uid, gid);
 356 
 357         /*
 358          * Store the results in r_secattr, n_uid, n_gid
 359          */
 360         mutex_enter(&np->r_statelock);
 361         ovsa = np->r_secattr;
 362         np->r_secattr = vsa;
 363         np->n_uid = uid;
 364         np->n_gid = gid;
 365         /*
 366          * ACLs don't change frequently, so cache these
 367          * for a relatively long time (ac dir max).
 368          */
 369         np->r_sectime = gethrtime() + smi->smi_acdirmax;
 370         mutex_exit(&np->r_statelock);
 371 
 372         /* Allocated in: smbfs_acl_sd2zfs */
 373         if (ovsa.vsa_aclentp != NULL)
 374                 kmem_free(ovsa.vsa_aclentp, ovsa.vsa_aclentsz);
 375 
 376 out:
 377         if (sd != NULL)
 378                 smbfs_acl_free_sd(sd);
 379         /* Note: m_freem(m) is done by... */
 380         md_done(mdp);
 381 
 382         return (error);
 383 }
 384 
 385 /*
 386  * Helper for smbfsgetattr()
 387  *
 388  * Just refresh the ACL cache if needed,
 389  * which updates n_uid/n_gid
 390  */
 391 int
 392 smbfs_acl_getids(vnode_t *vp, cred_t *cr)
 393 {
 394         smbnode_t *np;
 395         int error;
 396 
 397         np = VTOSMB(vp);
 398 
 399         /*
 400          * NB: extended attribute files and directories
 401          * do not have ACLs separate from the parent.
 402          * Let the caller do ACL fabrication.
 403          */
 404         if (np->n_flag & N_XATTR)
 405                 return (ENOSYS);
 406 
 407         mutex_enter(&np->r_statelock);
 408         if (gethrtime() >= np->r_sectime) {
 409                 /* Need to update r_secattr */
 410                 mutex_exit(&np->r_statelock);
 411                 error = smbfs_acl_refresh(vp, cr);
 412                 return (error);
 413         }
 414         mutex_exit(&np->r_statelock);
 415 
 416         return (0);
 417 }
 418 
 419 /*
 420  * Helper for VOP_GETSECATTR
 421  *
 422  * Refresh the ACL cache if needed, then
 423  * duplicate the requested parts of the vsecattr.
 424  */
 425 /* ARGSUSED */
 426 int
 427 smbfs_acl_getvsa(vnode_t *vp, vsecattr_t *vsa,
 428         int flag, cred_t *cr)
 429 {
 430         smbnode_t *np;
 431         int error;
 432 
 433         np = VTOSMB(vp);
 434 
 435         /*
 436          * NB: extended attribute files and directories
 437          * do not have ACLs separate from the parent.
 438          * Let the caller do ACL fabrication.
 439          */
 440         if (np->n_flag & N_XATTR)
 441                 return (ENOSYS);
 442 
 443         mutex_enter(&np->r_statelock);
 444 
 445         if (np->r_secattr.vsa_aclentp == NULL ||
 446             gethrtime() >= np->r_sectime) {
 447                 /* Need to update r_secattr */
 448                 mutex_exit(&np->r_statelock);
 449 
 450                 error = smbfs_acl_refresh(vp, cr);
 451                 if (error)
 452                         return (error);
 453 
 454                 mutex_enter(&np->r_statelock);
 455         }
 456         ASSERT(np->r_secattr.vsa_aclentp != NULL);
 457 
 458         /*
 459          * Duplicate requested parts of r_secattr
 460          */
 461 
 462         if (vsa->vsa_mask & VSA_ACECNT)
 463                 vsa->vsa_aclcnt = np->r_secattr.vsa_aclcnt;
 464 
 465         if (vsa->vsa_mask & VSA_ACE) {
 466                 vsa->vsa_aclentsz = np->r_secattr.vsa_aclentsz;
 467                 vsa->vsa_aclentp = kmem_alloc(vsa->vsa_aclentsz, KM_SLEEP);
 468                 bcopy(np->r_secattr.vsa_aclentp, vsa->vsa_aclentp,
 469                     vsa->vsa_aclentsz);
 470         }
 471 
 472         mutex_exit(&np->r_statelock);
 473         return (0);
 474 }
 475 
 476 /*
 477  * Helper for smbfs_acl_setids, smbfs_acl_setvsa
 478  */
 479 static int
 480 smbfs_acl_store(vnode_t *vp, vsecattr_t *vsa, uid_t uid, gid_t gid,
 481         uint32_t selector, cred_t *cr)
 482 {
 483         mbchain_t *mbp, mb_store;
 484         i_ntsd_t *sd;
 485         int error;
 486 
 487         ASSERT(selector != 0);
 488 
 489         sd = NULL;
 490         bzero(&mb_store, sizeof (mb_store));
 491         mbp = &mb_store;
 492 
 493         /*
 494          * Convert a ZFS ACL (and owner ID, group ID)
 495          * into an NT SD, internal form.
 496          */
 497         error = smbfs_acl_zfs2sd(vsa, uid, gid, selector, &sd);
 498         if (error)
 499                 goto out;
 500 
 501         /*
 502          * Marshall the internal form SD into an
 503          * OtW security descriptor.
 504          */
 505         (void) mb_init(mbp);
 506         error = mb_put_ntsd(mbp, sd);
 507         if (error)
 508                 goto out;
 509 
 510         /*
 511          * This does the OTW Set (and maybe open, close)
 512          * It clears mb_top when consuming the message.
 513          */
 514         error = smbfs_setsd(vp, selector, &mbp->mb_top, cr);
 515 
 516 out:
 517         if (sd != NULL)
 518                 smbfs_acl_free_sd(sd);
 519         mb_done(mbp);
 520         return (error);
 521 }
 522 
 523 /*
 524  * Helper for smbfs_setattr()
 525  *
 526  * Set the passed UID/GID as indicated by va_mask.
 527  */
 528 int
 529 smbfs_acl_setids(vnode_t *vp, vattr_t *vap, cred_t *cr)
 530 {
 531         uid_t uid = (uid_t)-1;
 532         gid_t gid = (uid_t)-1;
 533         uint32_t selector = 0;
 534         int error;
 535 
 536         if (vap->va_mask & AT_UID) {
 537                 selector |= OWNER_SECURITY_INFORMATION;
 538                 uid = vap->va_uid;
 539         }
 540 
 541         if (vap->va_mask & AT_GID) {
 542                 selector |= GROUP_SECURITY_INFORMATION;
 543                 gid = vap->va_gid;
 544         }
 545 
 546         if (selector == 0)
 547                 return (0);
 548 
 549         error = smbfs_acl_store(vp, NULL, uid, gid, selector, cr);
 550         return (error);
 551 }
 552 
 553 /*
 554  * Helper for VOP_SETSECATTR
 555  * Convert ZFS to NT form, call smbfs_setsd.
 556  */
 557 /* ARGSUSED */
 558 int
 559 smbfs_acl_setvsa(vnode_t *vp, vsecattr_t *vsa,
 560         int flag, cred_t *cr)
 561 {
 562         uint32_t selector = DACL_SECURITY_INFORMATION;
 563         smbnode_t *np = VTOSMB(vp);
 564         int error;
 565 
 566         /*
 567          * NB: extended attribute files and directories
 568          * do not have ACLs separate from the parent.
 569          */
 570         if (np->n_flag & N_XATTR)
 571                 return (ENOSYS);
 572 
 573         /*
 574          * When handling ACE_OWNER or ACE_GROUP entries,
 575          * we need the current owner and group.
 576          */
 577         error = smbfs_acl_getids(vp, cr);
 578         if (error)
 579                 return (error);
 580 
 581         error = smbfs_acl_store(vp, vsa, np->n_uid, np->n_gid, selector, cr);
 582         return (error);
 583 }