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*10023SGordon.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 52*10023SGordon.Ross@Sun.COM #include <netsmb/smb.h> 536711Sgwr #include <netsmb/smb_lib.h> 546711Sgwr #include <netsmb/smbfs_acl.h> 55*10023SGordon.Ross@Sun.COM 56*10023SGordon.Ross@Sun.COM #include "acl_nt.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 816711Sgwr error = mb_init(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 */ 1606711Sgwr error = mb_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; 1776711Sgwr mb_init(mbp, M_MINSIZE); 1786711Sgwr 1796711Sgwr /* 1806711Sgwr * Export the "internal" SD into an mb chain. 1816711Sgwr * (a.k.a "self-relative" form per. NT docs) 1826711Sgwr * Returns allocated mbchain in mbp. 1836711Sgwr */ 1846711Sgwr error = mb_put_ntsd(mbp, sd); 1856711Sgwr if (error == 0) { 1866711Sgwr /* 1876711Sgwr * Set the raw Windows SD via ioctl. 1886711Sgwr */ 1896711Sgwr error = smbfs_acl_iocset(fd, selector, mbp); 1906711Sgwr } 1916711Sgwr 1926711Sgwr mb_done(mbp); 1936711Sgwr 1946711Sgwr return (error); 1956711Sgwr } 1966711Sgwr 1976711Sgwr 1986711Sgwr 1996711Sgwr /* 2006711Sgwr * Convenience function to Get security using a 2016711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2026711Sgwr * Intentionally similar to: facl_get(3SEC) 2036711Sgwr */ 2046711Sgwr int 2056711Sgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp) 2066711Sgwr { 2076711Sgwr i_ntsd_t *sd = NULL; 2086711Sgwr acl_t *acl = NULL; 2096711Sgwr uint32_t selector; 2106711Sgwr int error; 2116711Sgwr 2126711Sgwr /* 2136711Sgwr * Which parts of the SD are being requested? 2146711Sgwr * XXX: Should we request the SACL too? If so, 2156711Sgwr * might that cause this access to be denied? 2166711Sgwr * Or maybe: if we get access denied, try the 2176711Sgwr * open/fetch again without the SACL bit. 2186711Sgwr */ 2196711Sgwr selector = 0; 2206711Sgwr if (aclp) 2216711Sgwr selector |= DACL_SECURITY_INFORMATION; 2226711Sgwr if (uidp) 2236711Sgwr selector |= OWNER_SECURITY_INFORMATION; 2246711Sgwr if (gidp) 2256711Sgwr selector |= GROUP_SECURITY_INFORMATION; 2266711Sgwr 2276711Sgwr if (selector == 0) 2286711Sgwr return (0); 2296711Sgwr 2306711Sgwr /* 2316711Sgwr * Get the Windows SD via ioctl, in 2326711Sgwr * "internal" (absolute) form. 2336711Sgwr */ 2346711Sgwr error = smbfs_acl_getsd(fd, selector, &sd); 2356711Sgwr if (error) 2366711Sgwr return (error); 2376711Sgwr /* Note: sd now holds allocated data. */ 2386711Sgwr 2396711Sgwr /* 2406711Sgwr * Convert the internal SD to a ZFS ACL. 2416711Sgwr * Get uid/gid too if pointers != NULL. 2426711Sgwr */ 2436711Sgwr if (aclp) { 2446711Sgwr acl = acl_alloc(ACE_T); 2456711Sgwr if (acl == NULL) { 2466711Sgwr error = ENOMEM; 2476711Sgwr goto out; 2486711Sgwr } 2496711Sgwr } 2506711Sgwr error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp); 2516711Sgwr if (error) 2526711Sgwr goto out; 2536711Sgwr 2546711Sgwr /* Success! */ 2556711Sgwr if (aclp) { 2566711Sgwr *aclp = acl; 2576711Sgwr acl = NULL; 2586711Sgwr } 2596711Sgwr 2606711Sgwr out: 2616711Sgwr if (acl) 2626711Sgwr acl_free(acl); 2636711Sgwr smbfs_acl_free_sd(sd); 2646711Sgwr return (error); 2656711Sgwr } 2666711Sgwr 2676711Sgwr /* 2686711Sgwr * Convenience function to Set security using a 2696711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2706711Sgwr * Intentionally similar to: facl_set(3SEC) 2716711Sgwr */ 2726711Sgwr int 2736711Sgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid) 2746711Sgwr { 2756711Sgwr i_ntsd_t *sd = NULL; 2766711Sgwr uint32_t selector; 2776711Sgwr int error; 2786711Sgwr 2796711Sgwr /* 2806711Sgwr * Which parts of the SD are being modified? 2816711Sgwr * XXX: Ditto comments above re. SACL. 2826711Sgwr */ 2836711Sgwr selector = 0; 2846711Sgwr if (acl) 2856711Sgwr selector |= DACL_SECURITY_INFORMATION; 2866711Sgwr if (uid != (uid_t)-1) 2876711Sgwr selector |= OWNER_SECURITY_INFORMATION; 2886711Sgwr if (gid != (gid_t)-1) 2896711Sgwr selector |= GROUP_SECURITY_INFORMATION; 2906711Sgwr if (selector == 0) 2916711Sgwr return (0); 2926711Sgwr 2936711Sgwr if (acl && acl->acl_type != ACE_T) 2946711Sgwr return (EINVAL); 2956711Sgwr 2966711Sgwr /* 2976711Sgwr * Convert the ZFS ACL to an internal SD. 2986711Sgwr * Returns allocated data in sd 2996711Sgwr */ 3006711Sgwr error = smbfs_acl_zfs2sd(acl, uid, gid, &sd); 3016711Sgwr if (error == 0) 3026711Sgwr error = smbfs_acl_setsd(fd, selector, sd); 3036711Sgwr 3046711Sgwr smbfs_acl_free_sd(sd); 3056711Sgwr 3066711Sgwr return (error); 3076711Sgwr } 308