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
smbfs_acl_iocget(int fd,uint32_t selector,mbdata_t * mbp)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
smbfs_acl_iocset(int fd,uint32_t selector,mbdata_t * mbp)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
smbfs_acl_getsd(int fd,uint32_t selector,i_ntsd_t ** sdp)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
smbfs_acl_setsd(int fd,uint32_t selector,i_ntsd_t * sd)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
smbfs_acl_get(int fd,acl_t ** aclp,uid_t * uidp,gid_t * gidp)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
smbfs_acl_set(int fd,acl_t * acl,uid_t uid,gid_t gid)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