17568150aSgwr /* 27568150aSgwr * CDDL HEADER START 37568150aSgwr * 47568150aSgwr * The contents of this file are subject to the terms of the 57568150aSgwr * Common Development and Distribution License (the "License"). 67568150aSgwr * You may not use this file except in compliance with the License. 77568150aSgwr * 87568150aSgwr * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97568150aSgwr * or http://www.opensolaris.org/os/licensing. 107568150aSgwr * See the License for the specific language governing permissions 117568150aSgwr * and limitations under the License. 127568150aSgwr * 137568150aSgwr * When distributing Covered Code, include this CDDL HEADER in each 147568150aSgwr * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157568150aSgwr * If applicable, add the following below this CDDL HEADER, with the 167568150aSgwr * fields enclosed by brackets "[]" replaced with your own identifying 177568150aSgwr * information: Portions Copyright [yyyy] [name of copyright owner] 187568150aSgwr * 197568150aSgwr * CDDL HEADER END 207568150aSgwr */ 217568150aSgwr 227568150aSgwr /* 23*bd7c6f51SGordon Ross * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247568150aSgwr * Use is subject to license terms. 257568150aSgwr */ 267568150aSgwr 277568150aSgwr /* 287568150aSgwr * ACL API for smbfs 297568150aSgwr */ 307568150aSgwr 317568150aSgwr #include <sys/types.h> 327568150aSgwr #include <sys/errno.h> 337568150aSgwr #include <sys/cred.h> 347568150aSgwr #include <sys/cmn_err.h> 357568150aSgwr #include <sys/kmem.h> 367568150aSgwr #include <sys/sunddi.h> 377568150aSgwr #include <sys/acl.h> 387568150aSgwr #include <sys/vnode.h> 397568150aSgwr #include <sys/vfs.h> 407568150aSgwr #include <sys/byteorder.h> 417568150aSgwr 427568150aSgwr #include <errno.h> 437568150aSgwr #include <stdio.h> 447568150aSgwr #include <strings.h> 457568150aSgwr #include <unistd.h> 467568150aSgwr 477568150aSgwr #include <umem.h> 487568150aSgwr #include <idmap.h> 497568150aSgwr 507568150aSgwr #include <sys/fs/smbfs_ioctl.h> 517568150aSgwr 52613a2f6bSGordon Ross #include <netsmb/smb.h> 537568150aSgwr #include <netsmb/smb_lib.h> 547568150aSgwr #include <netsmb/smbfs_acl.h> 55613a2f6bSGordon Ross 5602d09e03SGordon Ross #include "smbfs_ntacl.h" 579c9af259SGordon Ross #include "private.h" 587568150aSgwr 597568150aSgwr /* Sanity check SD sizes */ 607568150aSgwr #define MAX_RAW_SD_SIZE 32768 617568150aSgwr 627568150aSgwr /* XXX: acl_common.h */ 637568150aSgwr acl_t *acl_alloc(enum acl_type); 647568150aSgwr void acl_free(acl_t *); 657568150aSgwr 667568150aSgwr 677568150aSgwr /* 687568150aSgwr * Get/set a Windows security descriptor (SD) 697568150aSgwr * using the (private) smbfs ioctl mechanism. 707568150aSgwr * Note: Get allocates mbp->mb_top 717568150aSgwr */ 727568150aSgwr 737568150aSgwr /* ARGSUSED */ 747568150aSgwr int 757568150aSgwr smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) 767568150aSgwr { 777568150aSgwr ioc_sdbuf_t iocb; 787568150aSgwr struct mbuf *m; 797568150aSgwr int error; 807568150aSgwr 8102d09e03SGordon Ross error = mb_init_sz(mbp, MAX_RAW_SD_SIZE); 827568150aSgwr if (error) 837568150aSgwr return (error); 847568150aSgwr 857568150aSgwr m = mbp->mb_top; 867568150aSgwr iocb.addr = mtod(m, uintptr_t); 877568150aSgwr iocb.alloc = m->m_maxlen; 887568150aSgwr iocb.used = 0; 897568150aSgwr iocb.selector = selector; 907568150aSgwr 917568150aSgwr /* 927568150aSgwr * This does the OTW Get. 937568150aSgwr */ 947568150aSgwr if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { 957568150aSgwr error = errno; 967568150aSgwr goto errout; 977568150aSgwr } 987568150aSgwr 997568150aSgwr m->m_len = iocb.used; 1007568150aSgwr return (0); 1017568150aSgwr 1027568150aSgwr errout: 1037568150aSgwr mb_done(mbp); 1047568150aSgwr return (error); 1057568150aSgwr } 1067568150aSgwr 1077568150aSgwr /* ARGSUSED */ 1087568150aSgwr int 1097568150aSgwr smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) 1107568150aSgwr { 1117568150aSgwr ioc_sdbuf_t iocb; 1127568150aSgwr struct mbuf *m; 1137568150aSgwr int error; 1147568150aSgwr 1157568150aSgwr /* Make the data contiguous. */ 1167568150aSgwr error = m_lineup(mbp->mb_top, &m); 1177568150aSgwr if (error) 1187568150aSgwr return (error); 1197568150aSgwr 1207568150aSgwr if (mbp->mb_top != m) 1217568150aSgwr mb_initm(mbp, m); 1227568150aSgwr 1237568150aSgwr iocb.addr = mtod(m, uintptr_t); 1247568150aSgwr iocb.alloc = m->m_maxlen; 1257568150aSgwr iocb.used = m->m_len; 1267568150aSgwr iocb.selector = selector; 1277568150aSgwr 1287568150aSgwr /* 1297568150aSgwr * This does the OTW Set. 1307568150aSgwr */ 1317568150aSgwr if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) 1327568150aSgwr error = errno; 1337568150aSgwr 1347568150aSgwr return (error); 1357568150aSgwr } 1367568150aSgwr 1377568150aSgwr /* 1387568150aSgwr * Get an NT SD from the open file via ioctl. 1397568150aSgwr */ 1407568150aSgwr int 1417568150aSgwr smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp) 1427568150aSgwr { 1437568150aSgwr mbdata_t *mbp, mb_store; 1447568150aSgwr int error; 1457568150aSgwr 1467568150aSgwr mbp = &mb_store; 1477568150aSgwr bzero(mbp, sizeof (*mbp)); 1487568150aSgwr 1497568150aSgwr /* 1507568150aSgwr * Get the raw Windows SD via ioctl. 1517568150aSgwr * Returns allocated mbchain in mbp. 1527568150aSgwr */ 1537568150aSgwr error = smbfs_acl_iocget(fd, selector, mbp); 1547568150aSgwr if (error == 0) { 1557568150aSgwr /* 1567568150aSgwr * Import the raw SD into "internal" form. 1577568150aSgwr * (like "absolute" form per. NT docs) 1587568150aSgwr * Returns allocated data in sdp 1597568150aSgwr */ 16002d09e03SGordon Ross error = md_get_ntsd(mbp, sdp); 1617568150aSgwr } 1627568150aSgwr 1637568150aSgwr mb_done(mbp); 1647568150aSgwr return (error); 1657568150aSgwr } 1667568150aSgwr 1677568150aSgwr /* 1687568150aSgwr * Set an NT SD onto the open file via ioctl. 1697568150aSgwr */ 1707568150aSgwr int 1717568150aSgwr smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd) 1727568150aSgwr { 1737568150aSgwr mbdata_t *mbp, mb_store; 1747568150aSgwr int error; 1757568150aSgwr 1767568150aSgwr mbp = &mb_store; 17702d09e03SGordon Ross error = mb_init_sz(mbp, MAX_RAW_SD_SIZE); 17802d09e03SGordon Ross if (error) 17902d09e03SGordon Ross return (error); 1807568150aSgwr 1817568150aSgwr /* 1827568150aSgwr * Export the "internal" SD into an mb chain. 1837568150aSgwr * (a.k.a "self-relative" form per. NT docs) 1847568150aSgwr * Returns allocated mbchain in mbp. 1857568150aSgwr */ 1867568150aSgwr error = mb_put_ntsd(mbp, sd); 1877568150aSgwr if (error == 0) { 1887568150aSgwr /* 1897568150aSgwr * Set the raw Windows SD via ioctl. 1907568150aSgwr */ 1917568150aSgwr error = smbfs_acl_iocset(fd, selector, mbp); 1927568150aSgwr } 1937568150aSgwr 1947568150aSgwr mb_done(mbp); 1957568150aSgwr 1967568150aSgwr return (error); 1977568150aSgwr } 1987568150aSgwr 1997568150aSgwr 2007568150aSgwr 2017568150aSgwr /* 2027568150aSgwr * Convenience function to Get security using a 2037568150aSgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2047568150aSgwr * Intentionally similar to: facl_get(3SEC) 2057568150aSgwr */ 2067568150aSgwr int 2077568150aSgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp) 2087568150aSgwr { 2097568150aSgwr i_ntsd_t *sd = NULL; 2107568150aSgwr acl_t *acl = NULL; 2117568150aSgwr uint32_t selector; 2127568150aSgwr int error; 2137568150aSgwr 2147568150aSgwr /* 2157568150aSgwr * Which parts of the SD are being requested? 2167568150aSgwr * XXX: Should we request the SACL too? If so, 2177568150aSgwr * might that cause this access to be denied? 2187568150aSgwr * Or maybe: if we get access denied, try the 2197568150aSgwr * open/fetch again without the SACL bit. 2207568150aSgwr */ 2217568150aSgwr selector = 0; 2227568150aSgwr if (aclp) 2237568150aSgwr selector |= DACL_SECURITY_INFORMATION; 2247568150aSgwr if (uidp) 2257568150aSgwr selector |= OWNER_SECURITY_INFORMATION; 2267568150aSgwr if (gidp) 2277568150aSgwr selector |= GROUP_SECURITY_INFORMATION; 2287568150aSgwr 2297568150aSgwr if (selector == 0) 2307568150aSgwr return (0); 2317568150aSgwr 2327568150aSgwr /* 2337568150aSgwr * Get the Windows SD via ioctl, in 2347568150aSgwr * "internal" (absolute) form. 2357568150aSgwr */ 2367568150aSgwr error = smbfs_acl_getsd(fd, selector, &sd); 2377568150aSgwr if (error) 2387568150aSgwr return (error); 2397568150aSgwr /* Note: sd now holds allocated data. */ 2407568150aSgwr 2417568150aSgwr /* 2427568150aSgwr * Convert the internal SD to a ZFS ACL. 2437568150aSgwr * Get uid/gid too if pointers != NULL. 2447568150aSgwr */ 2457568150aSgwr if (aclp) { 2467568150aSgwr acl = acl_alloc(ACE_T); 2477568150aSgwr if (acl == NULL) { 2487568150aSgwr error = ENOMEM; 2497568150aSgwr goto out; 2507568150aSgwr } 2517568150aSgwr } 2527568150aSgwr error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp); 2537568150aSgwr if (error) 2547568150aSgwr goto out; 2557568150aSgwr 2567568150aSgwr /* Success! */ 2577568150aSgwr if (aclp) { 2587568150aSgwr *aclp = acl; 2597568150aSgwr acl = NULL; 2607568150aSgwr } 2617568150aSgwr 2627568150aSgwr out: 2637568150aSgwr if (acl) 2647568150aSgwr acl_free(acl); 2657568150aSgwr smbfs_acl_free_sd(sd); 2667568150aSgwr return (error); 2677568150aSgwr } 2687568150aSgwr 2697568150aSgwr /* 2707568150aSgwr * Convenience function to Set security using a 2717568150aSgwr * ZFS-style ACL (libsec acl, type=ACE_T) 2727568150aSgwr * Intentionally similar to: facl_set(3SEC) 2737568150aSgwr */ 2747568150aSgwr int 2757568150aSgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid) 2767568150aSgwr { 277*bd7c6f51SGordon Ross struct stat st; 2787568150aSgwr i_ntsd_t *sd = NULL; 2797568150aSgwr uint32_t selector; 2807568150aSgwr int error; 2817568150aSgwr 282*bd7c6f51SGordon Ross if (acl && acl->acl_type != ACE_T) 283*bd7c6f51SGordon Ross return (EINVAL); 284*bd7c6f51SGordon Ross 2857568150aSgwr /* 2867568150aSgwr * Which parts of the SD are being modified? 2877568150aSgwr * XXX: Ditto comments above re. SACL. 2887568150aSgwr */ 2897568150aSgwr selector = 0; 2907568150aSgwr if (acl) 2917568150aSgwr selector |= DACL_SECURITY_INFORMATION; 2927568150aSgwr if (uid != (uid_t)-1) 2937568150aSgwr selector |= OWNER_SECURITY_INFORMATION; 2947568150aSgwr if (gid != (gid_t)-1) 2957568150aSgwr selector |= GROUP_SECURITY_INFORMATION; 2967568150aSgwr if (selector == 0) 2977568150aSgwr return (0); 2987568150aSgwr 299*bd7c6f51SGordon Ross if (uid == (uid_t)-1 || gid == (gid_t)-1) { 300*bd7c6f51SGordon Ross /* 301*bd7c6f51SGordon Ross * If not setting owner or group, we need the 302*bd7c6f51SGordon Ross * current owner and group for translating 303*bd7c6f51SGordon Ross * references via owner@ or group@ ACEs. 304*bd7c6f51SGordon Ross */ 305*bd7c6f51SGordon Ross if (fstat(fd, &st) != 0) 306*bd7c6f51SGordon Ross return (errno); 307*bd7c6f51SGordon Ross if (uid == (uid_t)-1) 308*bd7c6f51SGordon Ross uid = st.st_uid; 309*bd7c6f51SGordon Ross if (gid == (gid_t)-1) 310*bd7c6f51SGordon Ross gid = st.st_gid; 311*bd7c6f51SGordon Ross } 3127568150aSgwr 3137568150aSgwr /* 3147568150aSgwr * Convert the ZFS ACL to an internal SD. 3157568150aSgwr * Returns allocated data in sd 3167568150aSgwr */ 317*bd7c6f51SGordon Ross error = smbfs_acl_zfs2sd(acl, uid, gid, selector, &sd); 3187568150aSgwr if (error == 0) 3197568150aSgwr error = smbfs_acl_setsd(fd, selector, sd); 3207568150aSgwr 3217568150aSgwr smbfs_acl_free_sd(sd); 3227568150aSgwr 3237568150aSgwr return (error); 3247568150aSgwr } 325