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 /* 2310023SGordon.Ross@Sun.COM * Copyright 2009 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 56*11332SGordon.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 81*11332SGordon.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 */ 160*11332SGordon.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; 177*11332SGordon.Ross@Sun.COM error = mb_init_sz(mbp, MAX_RAW_SD_SIZE); 178*11332SGordon.Ross@Sun.COM if (error) 179*11332SGordon.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 { 2776711Sgwr i_ntsd_t *sd = NULL; 2786711Sgwr uint32_t selector; 2796711Sgwr int error; 2806711Sgwr 2816711Sgwr /* 2826711Sgwr * Which parts of the SD are being modified? 2836711Sgwr * XXX: Ditto comments above re. SACL. 2846711Sgwr */ 2856711Sgwr selector = 0; 2866711Sgwr if (acl) 2876711Sgwr selector |= DACL_SECURITY_INFORMATION; 2886711Sgwr if (uid != (uid_t)-1) 2896711Sgwr selector |= OWNER_SECURITY_INFORMATION; 2906711Sgwr if (gid != (gid_t)-1) 2916711Sgwr selector |= GROUP_SECURITY_INFORMATION; 2926711Sgwr if (selector == 0) 2936711Sgwr return (0); 2946711Sgwr 2956711Sgwr if (acl && acl->acl_type != ACE_T) 2966711Sgwr return (EINVAL); 2976711Sgwr 2986711Sgwr /* 2996711Sgwr * Convert the ZFS ACL to an internal SD. 3006711Sgwr * Returns allocated data in sd 3016711Sgwr */ 3026711Sgwr error = smbfs_acl_zfs2sd(acl, uid, gid, &sd); 3036711Sgwr if (error == 0) 3046711Sgwr error = smbfs_acl_setsd(fd, selector, sd); 3056711Sgwr 3066711Sgwr smbfs_acl_free_sd(sd); 3076711Sgwr 3086711Sgwr return (error); 3096711Sgwr } 310