16711Sgwr /* 26711Sgwr * CDDL HEADER START 36711Sgwr * 46711Sgwr * The contents of this file are subject to the terms of the 56711Sgwr * Common Development and Distribution License (the "License"). 66711Sgwr * You may not use this file except in compliance with the License. 76711Sgwr * 86711Sgwr * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96711Sgwr * or http://www.opensolaris.org/os/licensing. 106711Sgwr * See the License for the specific language governing permissions 116711Sgwr * and limitations under the License. 126711Sgwr * 136711Sgwr * When distributing Covered Code, include this CDDL HEADER in each 146711Sgwr * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156711Sgwr * If applicable, add the following below this CDDL HEADER, with the 166711Sgwr * fields enclosed by brackets "[]" replaced with your own identifying 176711Sgwr * information: Portions Copyright [yyyy] [name of copyright owner] 186711Sgwr * 196711Sgwr * CDDL HEADER END 206711Sgwr */ 216711Sgwr 226711Sgwr /* 23*11564SGordon.Ross@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 246711Sgwr * Use is subject to license terms. 256711Sgwr */ 266711Sgwr 276711Sgwr /* 286711Sgwr * ACL API for smbfs 296711Sgwr */ 306711Sgwr 316711Sgwr #include <sys/types.h> 326711Sgwr #include <sys/errno.h> 336711Sgwr #include <sys/cred.h> 346711Sgwr #include <sys/cmn_err.h> 356711Sgwr #include <sys/kmem.h> 366711Sgwr #include <sys/sunddi.h> 376711Sgwr #include <sys/acl.h> 386711Sgwr #include <sys/vnode.h> 396711Sgwr #include <sys/vfs.h> 406711Sgwr #include <sys/byteorder.h> 416711Sgwr 426711Sgwr #include <errno.h> 436711Sgwr #include <stdio.h> 446711Sgwr #include <strings.h> 456711Sgwr #include <unistd.h> 466711Sgwr 476711Sgwr #include <umem.h> 486711Sgwr #include <idmap.h> 496711Sgwr 506711Sgwr #include <sys/fs/smbfs_ioctl.h> 516711Sgwr 5210023SGordon.Ross@Sun.COM #include <netsmb/smb.h> 536711Sgwr #include <netsmb/smb_lib.h> 546711Sgwr #include <netsmb/smbfs_acl.h> 5510023SGordon.Ross@Sun.COM 5611332SGordon.Ross@Sun.COM #include "smbfs_ntacl.h" 578271SGordon.Ross@Sun.COM #include "private.h" 586711Sgwr 596711Sgwr /* Sanity check SD sizes */ 606711Sgwr #define MAX_RAW_SD_SIZE 32768 616711Sgwr 626711Sgwr /* XXX: acl_common.h */ 636711Sgwr acl_t *acl_alloc(enum acl_type); 646711Sgwr void acl_free(acl_t *); 656711Sgwr 666711Sgwr 676711Sgwr /* 686711Sgwr * Get/set a Windows security descriptor (SD) 696711Sgwr * using the (private) smbfs ioctl mechanism. 706711Sgwr * Note: Get allocates mbp->mb_top 716711Sgwr */ 726711Sgwr 736711Sgwr /* ARGSUSED */ 746711Sgwr int 756711Sgwr smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) 766711Sgwr { 776711Sgwr ioc_sdbuf_t iocb; 786711Sgwr struct mbuf *m; 796711Sgwr int error; 806711Sgwr 8111332SGordon.Ross@Sun.COM error = mb_init_sz(mbp, MAX_RAW_SD_SIZE); 826711Sgwr if (error) 836711Sgwr return (error); 846711Sgwr 856711Sgwr m = mbp->mb_top; 866711Sgwr iocb.addr = mtod(m, uintptr_t); 876711Sgwr iocb.alloc = m->m_maxlen; 886711Sgwr iocb.used = 0; 896711Sgwr iocb.selector = selector; 906711Sgwr 916711Sgwr /* 926711Sgwr * This does the OTW Get. 936711Sgwr */ 946711Sgwr if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { 956711Sgwr error = errno; 966711Sgwr goto errout; 976711Sgwr } 986711Sgwr 996711Sgwr m->m_len = iocb.used; 1006711Sgwr return (0); 1016711Sgwr 1026711Sgwr errout: 1036711Sgwr mb_done(mbp); 1046711Sgwr return (error); 1056711Sgwr } 1066711Sgwr 1076711Sgwr /* ARGSUSED */ 1086711Sgwr int 1096711Sgwr smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) 1106711Sgwr { 1116711Sgwr ioc_sdbuf_t iocb; 1126711Sgwr struct mbuf *m; 1136711Sgwr int error; 1146711Sgwr 1156711Sgwr /* Make the data contiguous. */ 1166711Sgwr error = m_lineup(mbp->mb_top, &m); 1176711Sgwr if (error) 1186711Sgwr return (error); 1196711Sgwr 1206711Sgwr if (mbp->mb_top != m) 1216711Sgwr mb_initm(mbp, m); 1226711Sgwr 1236711Sgwr iocb.addr = mtod(m, uintptr_t); 1246711Sgwr iocb.alloc = m->m_maxlen; 1256711Sgwr iocb.used = m->m_len; 1266711Sgwr iocb.selector = selector; 1276711Sgwr 1286711Sgwr /* 1296711Sgwr * This does the OTW Set. 1306711Sgwr */ 1316711Sgwr if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) 1326711Sgwr error = errno; 1336711Sgwr 1346711Sgwr return (error); 1356711Sgwr } 1366711Sgwr 1376711Sgwr /* 1386711Sgwr * Get an NT SD from the open file via ioctl. 1396711Sgwr */ 1406711Sgwr int 1416711Sgwr smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp) 1426711Sgwr { 1436711Sgwr mbdata_t *mbp, mb_store; 1446711Sgwr int error; 1456711Sgwr 1466711Sgwr mbp = &mb_store; 1476711Sgwr bzero(mbp, sizeof (*mbp)); 1486711Sgwr 1496711Sgwr /* 1506711Sgwr * Get the raw Windows SD via ioctl. 1516711Sgwr * Returns allocated mbchain in mbp. 1526711Sgwr */ 1536711Sgwr error = smbfs_acl_iocget(fd, selector, mbp); 1546711Sgwr if (error == 0) { 1556711Sgwr /* 1566711Sgwr * Import the raw SD into "internal" form. 1576711Sgwr * (like "absolute" form per. NT docs) 1586711Sgwr * Returns allocated data in sdp 1596711Sgwr */ 16011332SGordon.Ross@Sun.COM error = md_get_ntsd(mbp, sdp); 1616711Sgwr } 1626711Sgwr 1636711Sgwr mb_done(mbp); 1646711Sgwr return (error); 1656711Sgwr } 1666711Sgwr 1676711Sgwr /* 1686711Sgwr * Set an NT SD onto the open file via ioctl. 1696711Sgwr */ 1706711Sgwr int 1716711Sgwr smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd) 1726711Sgwr { 1736711Sgwr mbdata_t *mbp, mb_store; 1746711Sgwr int error; 1756711Sgwr 1766711Sgwr mbp = &mb_store; 17711332SGordon.Ross@Sun.COM error = mb_init_sz(mbp, MAX_RAW_SD_SIZE); 17811332SGordon.Ross@Sun.COM if (error) 17911332SGordon.Ross@Sun.COM return (error); 1806711Sgwr 1816711Sgwr /* 1826711Sgwr * Export the "internal" SD into an mb chain. 1836711Sgwr * (a.k.a "self-relative" form per. NT docs) 1846711Sgwr * Returns allocated mbchain in mbp. 1856711Sgwr */ 1866711Sgwr error = mb_put_ntsd(mbp, sd); 1876711Sgwr if (error == 0) { 1886711Sgwr /* 1896711Sgwr * Set the raw Windows SD via ioctl. 1906711Sgwr */ 1916711Sgwr error = smbfs_acl_iocset(fd, selector, mbp); 1926711Sgwr } 1936711Sgwr 1946711Sgwr mb_done(mbp); 1956711Sgwr 1966711Sgwr return (error); 1976711Sgwr } 1986711Sgwr 1996711Sgwr 2006711Sgwr 2016711Sgwr /* 2026711Sgwr * Convenience function to Get security using a 2036711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2046711Sgwr * Intentionally similar to: facl_get(3SEC) 2056711Sgwr */ 2066711Sgwr int 2076711Sgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp) 2086711Sgwr { 2096711Sgwr i_ntsd_t *sd = NULL; 2106711Sgwr acl_t *acl = NULL; 2116711Sgwr uint32_t selector; 2126711Sgwr int error; 2136711Sgwr 2146711Sgwr /* 2156711Sgwr * Which parts of the SD are being requested? 2166711Sgwr * XXX: Should we request the SACL too? If so, 2176711Sgwr * might that cause this access to be denied? 2186711Sgwr * Or maybe: if we get access denied, try the 2196711Sgwr * open/fetch again without the SACL bit. 2206711Sgwr */ 2216711Sgwr selector = 0; 2226711Sgwr if (aclp) 2236711Sgwr selector |= DACL_SECURITY_INFORMATION; 2246711Sgwr if (uidp) 2256711Sgwr selector |= OWNER_SECURITY_INFORMATION; 2266711Sgwr if (gidp) 2276711Sgwr selector |= GROUP_SECURITY_INFORMATION; 2286711Sgwr 2296711Sgwr if (selector == 0) 2306711Sgwr return (0); 2316711Sgwr 2326711Sgwr /* 2336711Sgwr * Get the Windows SD via ioctl, in 2346711Sgwr * "internal" (absolute) form. 2356711Sgwr */ 2366711Sgwr error = smbfs_acl_getsd(fd, selector, &sd); 2376711Sgwr if (error) 2386711Sgwr return (error); 2396711Sgwr /* Note: sd now holds allocated data. */ 2406711Sgwr 2416711Sgwr /* 2426711Sgwr * Convert the internal SD to a ZFS ACL. 2436711Sgwr * Get uid/gid too if pointers != NULL. 2446711Sgwr */ 2456711Sgwr if (aclp) { 2466711Sgwr acl = acl_alloc(ACE_T); 2476711Sgwr if (acl == NULL) { 2486711Sgwr error = ENOMEM; 2496711Sgwr goto out; 2506711Sgwr } 2516711Sgwr } 2526711Sgwr error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp); 2536711Sgwr if (error) 2546711Sgwr goto out; 2556711Sgwr 2566711Sgwr /* Success! */ 2576711Sgwr if (aclp) { 2586711Sgwr *aclp = acl; 2596711Sgwr acl = NULL; 2606711Sgwr } 2616711Sgwr 2626711Sgwr out: 2636711Sgwr if (acl) 2646711Sgwr acl_free(acl); 2656711Sgwr smbfs_acl_free_sd(sd); 2666711Sgwr return (error); 2676711Sgwr } 2686711Sgwr 2696711Sgwr /* 2706711Sgwr * Convenience function to Set security using a 2716711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2726711Sgwr * Intentionally similar to: facl_set(3SEC) 2736711Sgwr */ 2746711Sgwr int 2756711Sgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid) 2766711Sgwr { 277*11564SGordon.Ross@Sun.COM struct stat st; 2786711Sgwr i_ntsd_t *sd = NULL; 2796711Sgwr uint32_t selector; 2806711Sgwr int error; 2816711Sgwr 282*11564SGordon.Ross@Sun.COM if (acl && acl->acl_type != ACE_T) 283*11564SGordon.Ross@Sun.COM return (EINVAL); 284*11564SGordon.Ross@Sun.COM 2856711Sgwr /* 2866711Sgwr * Which parts of the SD are being modified? 2876711Sgwr * XXX: Ditto comments above re. SACL. 2886711Sgwr */ 2896711Sgwr selector = 0; 2906711Sgwr if (acl) 2916711Sgwr selector |= DACL_SECURITY_INFORMATION; 2926711Sgwr if (uid != (uid_t)-1) 2936711Sgwr selector |= OWNER_SECURITY_INFORMATION; 2946711Sgwr if (gid != (gid_t)-1) 2956711Sgwr selector |= GROUP_SECURITY_INFORMATION; 2966711Sgwr if (selector == 0) 2976711Sgwr return (0); 2986711Sgwr 299*11564SGordon.Ross@Sun.COM if (uid == (uid_t)-1 || gid == (gid_t)-1) { 300*11564SGordon.Ross@Sun.COM /* 301*11564SGordon.Ross@Sun.COM * If not setting owner or group, we need the 302*11564SGordon.Ross@Sun.COM * current owner and group for translating 303*11564SGordon.Ross@Sun.COM * references via owner@ or group@ ACEs. 304*11564SGordon.Ross@Sun.COM */ 305*11564SGordon.Ross@Sun.COM if (fstat(fd, &st) != 0) 306*11564SGordon.Ross@Sun.COM return (errno); 307*11564SGordon.Ross@Sun.COM if (uid == (uid_t)-1) 308*11564SGordon.Ross@Sun.COM uid = st.st_uid; 309*11564SGordon.Ross@Sun.COM if (gid == (gid_t)-1) 310*11564SGordon.Ross@Sun.COM gid = st.st_gid; 311*11564SGordon.Ross@Sun.COM } 3126711Sgwr 3136711Sgwr /* 3146711Sgwr * Convert the ZFS ACL to an internal SD. 3156711Sgwr * Returns allocated data in sd 3166711Sgwr */ 317*11564SGordon.Ross@Sun.COM error = smbfs_acl_zfs2sd(acl, uid, gid, selector, &sd); 3186711Sgwr if (error == 0) 3196711Sgwr error = smbfs_acl_setsd(fd, selector, sd); 3206711Sgwr 3216711Sgwr smbfs_acl_free_sd(sd); 3226711Sgwr 3236711Sgwr return (error); 3246711Sgwr } 325