1*6711Sgwr /* 2*6711Sgwr * CDDL HEADER START 3*6711Sgwr * 4*6711Sgwr * The contents of this file are subject to the terms of the 5*6711Sgwr * Common Development and Distribution License (the "License"). 6*6711Sgwr * You may not use this file except in compliance with the License. 7*6711Sgwr * 8*6711Sgwr * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6711Sgwr * or http://www.opensolaris.org/os/licensing. 10*6711Sgwr * See the License for the specific language governing permissions 11*6711Sgwr * and limitations under the License. 12*6711Sgwr * 13*6711Sgwr * When distributing Covered Code, include this CDDL HEADER in each 14*6711Sgwr * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6711Sgwr * If applicable, add the following below this CDDL HEADER, with the 16*6711Sgwr * fields enclosed by brackets "[]" replaced with your own identifying 17*6711Sgwr * information: Portions Copyright [yyyy] [name of copyright owner] 18*6711Sgwr * 19*6711Sgwr * CDDL HEADER END 20*6711Sgwr */ 21*6711Sgwr 22*6711Sgwr /* 23*6711Sgwr * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*6711Sgwr * Use is subject to license terms. 25*6711Sgwr */ 26*6711Sgwr 27*6711Sgwr #pragma ident "%Z%%M% %I% %E% SMI" 28*6711Sgwr 29*6711Sgwr /* 30*6711Sgwr * ACL API for smbfs 31*6711Sgwr */ 32*6711Sgwr 33*6711Sgwr #include <sys/types.h> 34*6711Sgwr #include <sys/errno.h> 35*6711Sgwr #include <sys/cred.h> 36*6711Sgwr #include <sys/cmn_err.h> 37*6711Sgwr #include <sys/kmem.h> 38*6711Sgwr #include <sys/sunddi.h> 39*6711Sgwr #include <sys/acl.h> 40*6711Sgwr #include <sys/vnode.h> 41*6711Sgwr #include <sys/vfs.h> 42*6711Sgwr #include <sys/byteorder.h> 43*6711Sgwr 44*6711Sgwr #include <errno.h> 45*6711Sgwr #include <stdio.h> 46*6711Sgwr #include <strings.h> 47*6711Sgwr #include <unistd.h> 48*6711Sgwr 49*6711Sgwr #include <umem.h> 50*6711Sgwr #include <idmap.h> 51*6711Sgwr 52*6711Sgwr #include <sys/fs/smbfs_ioctl.h> 53*6711Sgwr 54*6711Sgwr #include <netsmb/smb_lib.h> 55*6711Sgwr #include <netsmb/smbfs_acl.h> 56*6711Sgwr #include <netsmb/smbfs_isec.h> 57*6711Sgwr 58*6711Sgwr /* Sanity check SD sizes */ 59*6711Sgwr #define MAX_RAW_SD_SIZE 32768 60*6711Sgwr 61*6711Sgwr /* XXX: acl_common.h */ 62*6711Sgwr acl_t *acl_alloc(enum acl_type); 63*6711Sgwr void acl_free(acl_t *); 64*6711Sgwr 65*6711Sgwr 66*6711Sgwr /* 67*6711Sgwr * Get/set a Windows security descriptor (SD) 68*6711Sgwr * using the (private) smbfs ioctl mechanism. 69*6711Sgwr * Note: Get allocates mbp->mb_top 70*6711Sgwr */ 71*6711Sgwr 72*6711Sgwr /* ARGSUSED */ 73*6711Sgwr int 74*6711Sgwr smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) 75*6711Sgwr { 76*6711Sgwr ioc_sdbuf_t iocb; 77*6711Sgwr struct mbuf *m; 78*6711Sgwr int error; 79*6711Sgwr 80*6711Sgwr error = mb_init(mbp, MAX_RAW_SD_SIZE); 81*6711Sgwr if (error) 82*6711Sgwr return (error); 83*6711Sgwr 84*6711Sgwr m = mbp->mb_top; 85*6711Sgwr iocb.addr = mtod(m, uintptr_t); 86*6711Sgwr iocb.alloc = m->m_maxlen; 87*6711Sgwr iocb.used = 0; 88*6711Sgwr iocb.selector = selector; 89*6711Sgwr 90*6711Sgwr /* 91*6711Sgwr * This does the OTW Get. 92*6711Sgwr */ 93*6711Sgwr if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { 94*6711Sgwr error = errno; 95*6711Sgwr goto errout; 96*6711Sgwr } 97*6711Sgwr 98*6711Sgwr m->m_len = iocb.used; 99*6711Sgwr return (0); 100*6711Sgwr 101*6711Sgwr errout: 102*6711Sgwr mb_done(mbp); 103*6711Sgwr return (error); 104*6711Sgwr } 105*6711Sgwr 106*6711Sgwr /* ARGSUSED */ 107*6711Sgwr int 108*6711Sgwr smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) 109*6711Sgwr { 110*6711Sgwr ioc_sdbuf_t iocb; 111*6711Sgwr struct mbuf *m; 112*6711Sgwr int error; 113*6711Sgwr 114*6711Sgwr /* Make the data contiguous. */ 115*6711Sgwr error = m_lineup(mbp->mb_top, &m); 116*6711Sgwr if (error) 117*6711Sgwr return (error); 118*6711Sgwr 119*6711Sgwr if (mbp->mb_top != m) 120*6711Sgwr mb_initm(mbp, m); 121*6711Sgwr 122*6711Sgwr iocb.addr = mtod(m, uintptr_t); 123*6711Sgwr iocb.alloc = m->m_maxlen; 124*6711Sgwr iocb.used = m->m_len; 125*6711Sgwr iocb.selector = selector; 126*6711Sgwr 127*6711Sgwr /* 128*6711Sgwr * This does the OTW Set. 129*6711Sgwr */ 130*6711Sgwr if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) 131*6711Sgwr error = errno; 132*6711Sgwr 133*6711Sgwr return (error); 134*6711Sgwr } 135*6711Sgwr 136*6711Sgwr /* 137*6711Sgwr * Get an NT SD from the open file via ioctl. 138*6711Sgwr */ 139*6711Sgwr int 140*6711Sgwr smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp) 141*6711Sgwr { 142*6711Sgwr mbdata_t *mbp, mb_store; 143*6711Sgwr int error; 144*6711Sgwr 145*6711Sgwr mbp = &mb_store; 146*6711Sgwr bzero(mbp, sizeof (*mbp)); 147*6711Sgwr 148*6711Sgwr /* 149*6711Sgwr * Get the raw Windows SD via ioctl. 150*6711Sgwr * Returns allocated mbchain in mbp. 151*6711Sgwr */ 152*6711Sgwr error = smbfs_acl_iocget(fd, selector, mbp); 153*6711Sgwr if (error == 0) { 154*6711Sgwr /* 155*6711Sgwr * Import the raw SD into "internal" form. 156*6711Sgwr * (like "absolute" form per. NT docs) 157*6711Sgwr * Returns allocated data in sdp 158*6711Sgwr */ 159*6711Sgwr error = mb_get_ntsd(mbp, sdp); 160*6711Sgwr } 161*6711Sgwr 162*6711Sgwr mb_done(mbp); 163*6711Sgwr return (error); 164*6711Sgwr } 165*6711Sgwr 166*6711Sgwr /* 167*6711Sgwr * Set an NT SD onto the open file via ioctl. 168*6711Sgwr */ 169*6711Sgwr int 170*6711Sgwr smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd) 171*6711Sgwr { 172*6711Sgwr mbdata_t *mbp, mb_store; 173*6711Sgwr int error; 174*6711Sgwr 175*6711Sgwr mbp = &mb_store; 176*6711Sgwr mb_init(mbp, M_MINSIZE); 177*6711Sgwr 178*6711Sgwr /* 179*6711Sgwr * Export the "internal" SD into an mb chain. 180*6711Sgwr * (a.k.a "self-relative" form per. NT docs) 181*6711Sgwr * Returns allocated mbchain in mbp. 182*6711Sgwr */ 183*6711Sgwr error = mb_put_ntsd(mbp, sd); 184*6711Sgwr if (error == 0) { 185*6711Sgwr /* 186*6711Sgwr * Set the raw Windows SD via ioctl. 187*6711Sgwr */ 188*6711Sgwr error = smbfs_acl_iocset(fd, selector, mbp); 189*6711Sgwr } 190*6711Sgwr 191*6711Sgwr mb_done(mbp); 192*6711Sgwr 193*6711Sgwr return (error); 194*6711Sgwr } 195*6711Sgwr 196*6711Sgwr 197*6711Sgwr 198*6711Sgwr /* 199*6711Sgwr * Convenience function to Get security using a 200*6711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 201*6711Sgwr * Intentionally similar to: facl_get(3SEC) 202*6711Sgwr */ 203*6711Sgwr int 204*6711Sgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp) 205*6711Sgwr { 206*6711Sgwr i_ntsd_t *sd = NULL; 207*6711Sgwr acl_t *acl = NULL; 208*6711Sgwr uint32_t selector; 209*6711Sgwr int error; 210*6711Sgwr 211*6711Sgwr /* 212*6711Sgwr * Which parts of the SD are being requested? 213*6711Sgwr * XXX: Should we request the SACL too? If so, 214*6711Sgwr * might that cause this access to be denied? 215*6711Sgwr * Or maybe: if we get access denied, try the 216*6711Sgwr * open/fetch again without the SACL bit. 217*6711Sgwr */ 218*6711Sgwr selector = 0; 219*6711Sgwr if (aclp) 220*6711Sgwr selector |= DACL_SECURITY_INFORMATION; 221*6711Sgwr if (uidp) 222*6711Sgwr selector |= OWNER_SECURITY_INFORMATION; 223*6711Sgwr if (gidp) 224*6711Sgwr selector |= GROUP_SECURITY_INFORMATION; 225*6711Sgwr 226*6711Sgwr if (selector == 0) 227*6711Sgwr return (0); 228*6711Sgwr 229*6711Sgwr /* 230*6711Sgwr * Get the Windows SD via ioctl, in 231*6711Sgwr * "internal" (absolute) form. 232*6711Sgwr */ 233*6711Sgwr error = smbfs_acl_getsd(fd, selector, &sd); 234*6711Sgwr if (error) 235*6711Sgwr return (error); 236*6711Sgwr /* Note: sd now holds allocated data. */ 237*6711Sgwr 238*6711Sgwr /* 239*6711Sgwr * Convert the internal SD to a ZFS ACL. 240*6711Sgwr * Get uid/gid too if pointers != NULL. 241*6711Sgwr */ 242*6711Sgwr if (aclp) { 243*6711Sgwr acl = acl_alloc(ACE_T); 244*6711Sgwr if (acl == NULL) { 245*6711Sgwr error = ENOMEM; 246*6711Sgwr goto out; 247*6711Sgwr } 248*6711Sgwr } 249*6711Sgwr error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp); 250*6711Sgwr if (error) 251*6711Sgwr goto out; 252*6711Sgwr 253*6711Sgwr /* Success! */ 254*6711Sgwr if (aclp) { 255*6711Sgwr *aclp = acl; 256*6711Sgwr acl = NULL; 257*6711Sgwr } 258*6711Sgwr 259*6711Sgwr out: 260*6711Sgwr if (acl) 261*6711Sgwr acl_free(acl); 262*6711Sgwr smbfs_acl_free_sd(sd); 263*6711Sgwr return (error); 264*6711Sgwr } 265*6711Sgwr 266*6711Sgwr /* 267*6711Sgwr * Convenience function to Set security using a 268*6711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 269*6711Sgwr * Intentionally similar to: facl_set(3SEC) 270*6711Sgwr */ 271*6711Sgwr int 272*6711Sgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid) 273*6711Sgwr { 274*6711Sgwr i_ntsd_t *sd = NULL; 275*6711Sgwr uint32_t selector; 276*6711Sgwr int error; 277*6711Sgwr 278*6711Sgwr /* 279*6711Sgwr * Which parts of the SD are being modified? 280*6711Sgwr * XXX: Ditto comments above re. SACL. 281*6711Sgwr */ 282*6711Sgwr selector = 0; 283*6711Sgwr if (acl) 284*6711Sgwr selector |= DACL_SECURITY_INFORMATION; 285*6711Sgwr if (uid != (uid_t)-1) 286*6711Sgwr selector |= OWNER_SECURITY_INFORMATION; 287*6711Sgwr if (gid != (gid_t)-1) 288*6711Sgwr selector |= GROUP_SECURITY_INFORMATION; 289*6711Sgwr if (selector == 0) 290*6711Sgwr return (0); 291*6711Sgwr 292*6711Sgwr if (acl && acl->acl_type != ACE_T) 293*6711Sgwr return (EINVAL); 294*6711Sgwr 295*6711Sgwr /* 296*6711Sgwr * Convert the ZFS ACL to an internal SD. 297*6711Sgwr * Returns allocated data in sd 298*6711Sgwr */ 299*6711Sgwr error = smbfs_acl_zfs2sd(acl, uid, gid, &sd); 300*6711Sgwr if (error == 0) 301*6711Sgwr error = smbfs_acl_setsd(fd, selector, sd); 302*6711Sgwr 303*6711Sgwr smbfs_acl_free_sd(sd); 304*6711Sgwr 305*6711Sgwr return (error); 306*6711Sgwr } 307