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 /* 236711Sgwr * Copyright 2008 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 526711Sgwr #include <netsmb/smb_lib.h> 536711Sgwr #include <netsmb/smbfs_acl.h> 546711Sgwr #include <netsmb/smbfs_isec.h> 55*8271SGordon.Ross@Sun.COM #include "private.h" 566711Sgwr 576711Sgwr /* Sanity check SD sizes */ 586711Sgwr #define MAX_RAW_SD_SIZE 32768 596711Sgwr 606711Sgwr /* XXX: acl_common.h */ 616711Sgwr acl_t *acl_alloc(enum acl_type); 626711Sgwr void acl_free(acl_t *); 636711Sgwr 646711Sgwr 656711Sgwr /* 666711Sgwr * Get/set a Windows security descriptor (SD) 676711Sgwr * using the (private) smbfs ioctl mechanism. 686711Sgwr * Note: Get allocates mbp->mb_top 696711Sgwr */ 706711Sgwr 716711Sgwr /* ARGSUSED */ 726711Sgwr int 736711Sgwr smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) 746711Sgwr { 756711Sgwr ioc_sdbuf_t iocb; 766711Sgwr struct mbuf *m; 776711Sgwr int error; 786711Sgwr 796711Sgwr error = mb_init(mbp, MAX_RAW_SD_SIZE); 806711Sgwr if (error) 816711Sgwr return (error); 826711Sgwr 836711Sgwr m = mbp->mb_top; 846711Sgwr iocb.addr = mtod(m, uintptr_t); 856711Sgwr iocb.alloc = m->m_maxlen; 866711Sgwr iocb.used = 0; 876711Sgwr iocb.selector = selector; 886711Sgwr 896711Sgwr /* 906711Sgwr * This does the OTW Get. 916711Sgwr */ 926711Sgwr if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { 936711Sgwr error = errno; 946711Sgwr goto errout; 956711Sgwr } 966711Sgwr 976711Sgwr m->m_len = iocb.used; 986711Sgwr return (0); 996711Sgwr 1006711Sgwr errout: 1016711Sgwr mb_done(mbp); 1026711Sgwr return (error); 1036711Sgwr } 1046711Sgwr 1056711Sgwr /* ARGSUSED */ 1066711Sgwr int 1076711Sgwr smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) 1086711Sgwr { 1096711Sgwr ioc_sdbuf_t iocb; 1106711Sgwr struct mbuf *m; 1116711Sgwr int error; 1126711Sgwr 1136711Sgwr /* Make the data contiguous. */ 1146711Sgwr error = m_lineup(mbp->mb_top, &m); 1156711Sgwr if (error) 1166711Sgwr return (error); 1176711Sgwr 1186711Sgwr if (mbp->mb_top != m) 1196711Sgwr mb_initm(mbp, m); 1206711Sgwr 1216711Sgwr iocb.addr = mtod(m, uintptr_t); 1226711Sgwr iocb.alloc = m->m_maxlen; 1236711Sgwr iocb.used = m->m_len; 1246711Sgwr iocb.selector = selector; 1256711Sgwr 1266711Sgwr /* 1276711Sgwr * This does the OTW Set. 1286711Sgwr */ 1296711Sgwr if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) 1306711Sgwr error = errno; 1316711Sgwr 1326711Sgwr return (error); 1336711Sgwr } 1346711Sgwr 1356711Sgwr /* 1366711Sgwr * Get an NT SD from the open file via ioctl. 1376711Sgwr */ 1386711Sgwr int 1396711Sgwr smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp) 1406711Sgwr { 1416711Sgwr mbdata_t *mbp, mb_store; 1426711Sgwr int error; 1436711Sgwr 1446711Sgwr mbp = &mb_store; 1456711Sgwr bzero(mbp, sizeof (*mbp)); 1466711Sgwr 1476711Sgwr /* 1486711Sgwr * Get the raw Windows SD via ioctl. 1496711Sgwr * Returns allocated mbchain in mbp. 1506711Sgwr */ 1516711Sgwr error = smbfs_acl_iocget(fd, selector, mbp); 1526711Sgwr if (error == 0) { 1536711Sgwr /* 1546711Sgwr * Import the raw SD into "internal" form. 1556711Sgwr * (like "absolute" form per. NT docs) 1566711Sgwr * Returns allocated data in sdp 1576711Sgwr */ 1586711Sgwr error = mb_get_ntsd(mbp, sdp); 1596711Sgwr } 1606711Sgwr 1616711Sgwr mb_done(mbp); 1626711Sgwr return (error); 1636711Sgwr } 1646711Sgwr 1656711Sgwr /* 1666711Sgwr * Set an NT SD onto the open file via ioctl. 1676711Sgwr */ 1686711Sgwr int 1696711Sgwr smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd) 1706711Sgwr { 1716711Sgwr mbdata_t *mbp, mb_store; 1726711Sgwr int error; 1736711Sgwr 1746711Sgwr mbp = &mb_store; 1756711Sgwr mb_init(mbp, M_MINSIZE); 1766711Sgwr 1776711Sgwr /* 1786711Sgwr * Export the "internal" SD into an mb chain. 1796711Sgwr * (a.k.a "self-relative" form per. NT docs) 1806711Sgwr * Returns allocated mbchain in mbp. 1816711Sgwr */ 1826711Sgwr error = mb_put_ntsd(mbp, sd); 1836711Sgwr if (error == 0) { 1846711Sgwr /* 1856711Sgwr * Set the raw Windows SD via ioctl. 1866711Sgwr */ 1876711Sgwr error = smbfs_acl_iocset(fd, selector, mbp); 1886711Sgwr } 1896711Sgwr 1906711Sgwr mb_done(mbp); 1916711Sgwr 1926711Sgwr return (error); 1936711Sgwr } 1946711Sgwr 1956711Sgwr 1966711Sgwr 1976711Sgwr /* 1986711Sgwr * Convenience function to Get security using a 1996711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2006711Sgwr * Intentionally similar to: facl_get(3SEC) 2016711Sgwr */ 2026711Sgwr int 2036711Sgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp) 2046711Sgwr { 2056711Sgwr i_ntsd_t *sd = NULL; 2066711Sgwr acl_t *acl = NULL; 2076711Sgwr uint32_t selector; 2086711Sgwr int error; 2096711Sgwr 2106711Sgwr /* 2116711Sgwr * Which parts of the SD are being requested? 2126711Sgwr * XXX: Should we request the SACL too? If so, 2136711Sgwr * might that cause this access to be denied? 2146711Sgwr * Or maybe: if we get access denied, try the 2156711Sgwr * open/fetch again without the SACL bit. 2166711Sgwr */ 2176711Sgwr selector = 0; 2186711Sgwr if (aclp) 2196711Sgwr selector |= DACL_SECURITY_INFORMATION; 2206711Sgwr if (uidp) 2216711Sgwr selector |= OWNER_SECURITY_INFORMATION; 2226711Sgwr if (gidp) 2236711Sgwr selector |= GROUP_SECURITY_INFORMATION; 2246711Sgwr 2256711Sgwr if (selector == 0) 2266711Sgwr return (0); 2276711Sgwr 2286711Sgwr /* 2296711Sgwr * Get the Windows SD via ioctl, in 2306711Sgwr * "internal" (absolute) form. 2316711Sgwr */ 2326711Sgwr error = smbfs_acl_getsd(fd, selector, &sd); 2336711Sgwr if (error) 2346711Sgwr return (error); 2356711Sgwr /* Note: sd now holds allocated data. */ 2366711Sgwr 2376711Sgwr /* 2386711Sgwr * Convert the internal SD to a ZFS ACL. 2396711Sgwr * Get uid/gid too if pointers != NULL. 2406711Sgwr */ 2416711Sgwr if (aclp) { 2426711Sgwr acl = acl_alloc(ACE_T); 2436711Sgwr if (acl == NULL) { 2446711Sgwr error = ENOMEM; 2456711Sgwr goto out; 2466711Sgwr } 2476711Sgwr } 2486711Sgwr error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp); 2496711Sgwr if (error) 2506711Sgwr goto out; 2516711Sgwr 2526711Sgwr /* Success! */ 2536711Sgwr if (aclp) { 2546711Sgwr *aclp = acl; 2556711Sgwr acl = NULL; 2566711Sgwr } 2576711Sgwr 2586711Sgwr out: 2596711Sgwr if (acl) 2606711Sgwr acl_free(acl); 2616711Sgwr smbfs_acl_free_sd(sd); 2626711Sgwr return (error); 2636711Sgwr } 2646711Sgwr 2656711Sgwr /* 2666711Sgwr * Convenience function to Set security using a 2676711Sgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2686711Sgwr * Intentionally similar to: facl_set(3SEC) 2696711Sgwr */ 2706711Sgwr int 2716711Sgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid) 2726711Sgwr { 2736711Sgwr i_ntsd_t *sd = NULL; 2746711Sgwr uint32_t selector; 2756711Sgwr int error; 2766711Sgwr 2776711Sgwr /* 2786711Sgwr * Which parts of the SD are being modified? 2796711Sgwr * XXX: Ditto comments above re. SACL. 2806711Sgwr */ 2816711Sgwr selector = 0; 2826711Sgwr if (acl) 2836711Sgwr selector |= DACL_SECURITY_INFORMATION; 2846711Sgwr if (uid != (uid_t)-1) 2856711Sgwr selector |= OWNER_SECURITY_INFORMATION; 2866711Sgwr if (gid != (gid_t)-1) 2876711Sgwr selector |= GROUP_SECURITY_INFORMATION; 2886711Sgwr if (selector == 0) 2896711Sgwr return (0); 2906711Sgwr 2916711Sgwr if (acl && acl->acl_type != ACE_T) 2926711Sgwr return (EINVAL); 2936711Sgwr 2946711Sgwr /* 2956711Sgwr * Convert the ZFS ACL to an internal SD. 2966711Sgwr * Returns allocated data in sd 2976711Sgwr */ 2986711Sgwr error = smbfs_acl_zfs2sd(acl, uid, gid, &sd); 2996711Sgwr if (error == 0) 3006711Sgwr error = smbfs_acl_setsd(fd, selector, sd); 3016711Sgwr 3026711Sgwr smbfs_acl_free_sd(sd); 3036711Sgwr 3046711Sgwr return (error); 3056711Sgwr } 306