xref: /illumos-gate/usr/src/lib/libsmbfs/smb/acl_api.c (revision 8329232e)
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 /*
23bd7c6f51SGordon Ross  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247568150aSgwr  * Use is subject to license terms.
25*8329232eSGordon Ross  *
26*8329232eSGordon Ross  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
277568150aSgwr  */
287568150aSgwr 
297568150aSgwr /*
307568150aSgwr  * ACL API for smbfs
317568150aSgwr  */
327568150aSgwr 
337568150aSgwr #include <sys/types.h>
347568150aSgwr #include <sys/errno.h>
357568150aSgwr #include <sys/cred.h>
367568150aSgwr #include <sys/cmn_err.h>
377568150aSgwr #include <sys/kmem.h>
387568150aSgwr #include <sys/sunddi.h>
397568150aSgwr #include <sys/acl.h>
407568150aSgwr #include <sys/vnode.h>
417568150aSgwr #include <sys/vfs.h>
427568150aSgwr #include <sys/byteorder.h>
437568150aSgwr 
447568150aSgwr #include <errno.h>
457568150aSgwr #include <stdio.h>
467568150aSgwr #include <strings.h>
477568150aSgwr #include <unistd.h>
487568150aSgwr 
497568150aSgwr #include <umem.h>
507568150aSgwr #include <idmap.h>
517568150aSgwr 
527568150aSgwr #include <sys/fs/smbfs_ioctl.h>
537568150aSgwr 
54613a2f6bSGordon Ross #include <netsmb/smb.h>
557568150aSgwr #include <netsmb/smb_lib.h>
567568150aSgwr #include <netsmb/smbfs_acl.h>
57613a2f6bSGordon Ross 
5802d09e03SGordon Ross #include "smbfs_ntacl.h"
599c9af259SGordon Ross #include "private.h"
607568150aSgwr 
617568150aSgwr /* Sanity check SD sizes */
627568150aSgwr #define	MAX_RAW_SD_SIZE	32768
637568150aSgwr 
647568150aSgwr /* XXX: acl_common.h */
657568150aSgwr acl_t *acl_alloc(enum acl_type);
667568150aSgwr void acl_free(acl_t *);
677568150aSgwr 
687568150aSgwr 
697568150aSgwr /*
707568150aSgwr  * Get/set a Windows security descriptor (SD)
717568150aSgwr  * using the (private) smbfs ioctl mechanism.
727568150aSgwr  * Note: Get allocates mbp->mb_top
737568150aSgwr  */
747568150aSgwr 
757568150aSgwr /* ARGSUSED */
767568150aSgwr int
smbfs_acl_iocget(int fd,uint32_t selector,mbdata_t * mbp)777568150aSgwr smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp)
787568150aSgwr {
797568150aSgwr 	ioc_sdbuf_t	iocb;
807568150aSgwr 	struct mbuf	*m;
817568150aSgwr 	int		error;
827568150aSgwr 
8302d09e03SGordon Ross 	error = mb_init_sz(mbp, MAX_RAW_SD_SIZE);
847568150aSgwr 	if (error)
857568150aSgwr 		return (error);
867568150aSgwr 
877568150aSgwr 	m = mbp->mb_top;
88*8329232eSGordon Ross 	bzero(&iocb, sizeof (iocb));
897568150aSgwr 	iocb.addr = mtod(m, uintptr_t);
907568150aSgwr 	iocb.alloc = m->m_maxlen;
917568150aSgwr 	iocb.used = 0;
927568150aSgwr 	iocb.selector = selector;
937568150aSgwr 
947568150aSgwr 	/*
957568150aSgwr 	 * This does the OTW Get.
967568150aSgwr 	 */
97*8329232eSGordon Ross 	if (nsmb_ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) {
987568150aSgwr 		error = errno;
997568150aSgwr 		goto errout;
1007568150aSgwr 	}
1017568150aSgwr 
1027568150aSgwr 	m->m_len = iocb.used;
1037568150aSgwr 	return (0);
1047568150aSgwr 
1057568150aSgwr errout:
1067568150aSgwr 	mb_done(mbp);
1077568150aSgwr 	return (error);
1087568150aSgwr }
1097568150aSgwr 
1107568150aSgwr /* ARGSUSED */
1117568150aSgwr int
smbfs_acl_iocset(int fd,uint32_t selector,mbdata_t * mbp)1127568150aSgwr smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp)
1137568150aSgwr {
1147568150aSgwr 	ioc_sdbuf_t	iocb;
1157568150aSgwr 	struct mbuf	*m;
1167568150aSgwr 	int		error;
1177568150aSgwr 
1187568150aSgwr 	/* Make the data contiguous. */
1197568150aSgwr 	error = m_lineup(mbp->mb_top, &m);
1207568150aSgwr 	if (error)
1217568150aSgwr 		return (error);
1227568150aSgwr 
1237568150aSgwr 	if (mbp->mb_top != m)
1247568150aSgwr 		mb_initm(mbp, m);
1257568150aSgwr 
126*8329232eSGordon Ross 	bzero(&iocb, sizeof (iocb));
1277568150aSgwr 	iocb.addr = mtod(m, uintptr_t);
1287568150aSgwr 	iocb.alloc = m->m_maxlen;
1297568150aSgwr 	iocb.used  = m->m_len;
1307568150aSgwr 	iocb.selector = selector;
1317568150aSgwr 
1327568150aSgwr 	/*
1337568150aSgwr 	 * This does the OTW Set.
1347568150aSgwr 	 */
135*8329232eSGordon Ross 	if (nsmb_ioctl(fd, SMBFSIO_SETSD, &iocb) < 0)
1367568150aSgwr 		error = errno;
1377568150aSgwr 
1387568150aSgwr 	return (error);
1397568150aSgwr }
1407568150aSgwr 
1417568150aSgwr /*
1427568150aSgwr  * Get an NT SD from the open file via ioctl.
1437568150aSgwr  */
1447568150aSgwr int
smbfs_acl_getsd(int fd,uint32_t selector,i_ntsd_t ** sdp)1457568150aSgwr smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp)
1467568150aSgwr {
1477568150aSgwr 	mbdata_t *mbp, mb_store;
1487568150aSgwr 	int error;
1497568150aSgwr 
1507568150aSgwr 	mbp = &mb_store;
1517568150aSgwr 	bzero(mbp, sizeof (*mbp));
1527568150aSgwr 
1537568150aSgwr 	/*
1547568150aSgwr 	 * Get the raw Windows SD via ioctl.
1557568150aSgwr 	 * Returns allocated mbchain in mbp.
1567568150aSgwr 	 */
1577568150aSgwr 	error = smbfs_acl_iocget(fd, selector, mbp);
1587568150aSgwr 	if (error == 0) {
1597568150aSgwr 		/*
1607568150aSgwr 		 * Import the raw SD into "internal" form.
1617568150aSgwr 		 * (like "absolute" form per. NT docs)
1627568150aSgwr 		 * Returns allocated data in sdp
1637568150aSgwr 		 */
16402d09e03SGordon Ross 		error = md_get_ntsd(mbp, sdp);
1657568150aSgwr 	}
1667568150aSgwr 
1677568150aSgwr 	mb_done(mbp);
1687568150aSgwr 	return (error);
1697568150aSgwr }
1707568150aSgwr 
1717568150aSgwr /*
1727568150aSgwr  * Set an NT SD onto the open file via ioctl.
1737568150aSgwr  */
1747568150aSgwr int
smbfs_acl_setsd(int fd,uint32_t selector,i_ntsd_t * sd)1757568150aSgwr smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd)
1767568150aSgwr {
1777568150aSgwr 	mbdata_t *mbp, mb_store;
1787568150aSgwr 	int error;
1797568150aSgwr 
1807568150aSgwr 	mbp = &mb_store;
18102d09e03SGordon Ross 	error = mb_init_sz(mbp, MAX_RAW_SD_SIZE);
18202d09e03SGordon Ross 	if (error)
18302d09e03SGordon Ross 		return (error);
1847568150aSgwr 
1857568150aSgwr 	/*
1867568150aSgwr 	 * Export the "internal" SD into an mb chain.
1877568150aSgwr 	 * (a.k.a "self-relative" form per. NT docs)
1887568150aSgwr 	 * Returns allocated mbchain in mbp.
1897568150aSgwr 	 */
1907568150aSgwr 	error = mb_put_ntsd(mbp, sd);
1917568150aSgwr 	if (error == 0) {
1927568150aSgwr 		/*
1937568150aSgwr 		 * Set the raw Windows SD via ioctl.
1947568150aSgwr 		 */
1957568150aSgwr 		error = smbfs_acl_iocset(fd, selector, mbp);
1967568150aSgwr 	}
1977568150aSgwr 
1987568150aSgwr 	mb_done(mbp);
1997568150aSgwr 
2007568150aSgwr 	return (error);
2017568150aSgwr }
2027568150aSgwr 
2037568150aSgwr 
2047568150aSgwr 
2057568150aSgwr /*
2067568150aSgwr  * Convenience function to Get security using a
2077568150aSgwr  * ZFS-style ACL (libsec acl, type=ACE_T)
2087568150aSgwr  * Intentionally similar to: facl_get(3SEC)
2097568150aSgwr  */
2107568150aSgwr int
smbfs_acl_get(int fd,acl_t ** aclp,uid_t * uidp,gid_t * gidp)2117568150aSgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp)
2127568150aSgwr {
2137568150aSgwr 	i_ntsd_t *sd = NULL;
2147568150aSgwr 	acl_t *acl = NULL;
2157568150aSgwr 	uint32_t selector;
2167568150aSgwr 	int error;
2177568150aSgwr 
2187568150aSgwr 	/*
2197568150aSgwr 	 * Which parts of the SD are being requested?
2207568150aSgwr 	 * XXX: Should we request the SACL too?  If so,
2217568150aSgwr 	 * might that cause this access to be denied?
2227568150aSgwr 	 * Or maybe: if we get access denied, try the
2237568150aSgwr 	 * open/fetch again without the SACL bit.
2247568150aSgwr 	 */
2257568150aSgwr 	selector = 0;
2267568150aSgwr 	if (aclp)
2277568150aSgwr 		selector |= DACL_SECURITY_INFORMATION;
2287568150aSgwr 	if (uidp)
2297568150aSgwr 		selector |= OWNER_SECURITY_INFORMATION;
2307568150aSgwr 	if (gidp)
2317568150aSgwr 		selector |= GROUP_SECURITY_INFORMATION;
2327568150aSgwr 
2337568150aSgwr 	if (selector == 0)
2347568150aSgwr 		return (0);
2357568150aSgwr 
2367568150aSgwr 	/*
2377568150aSgwr 	 * Get the Windows SD via ioctl, in
2387568150aSgwr 	 * "internal" (absolute) form.
2397568150aSgwr 	 */
2407568150aSgwr 	error = smbfs_acl_getsd(fd, selector, &sd);
2417568150aSgwr 	if (error)
2427568150aSgwr 		return (error);
2437568150aSgwr 	/* Note: sd now holds allocated data. */
2447568150aSgwr 
2457568150aSgwr 	/*
2467568150aSgwr 	 * Convert the internal SD to a ZFS ACL.
2477568150aSgwr 	 * Get uid/gid too if pointers != NULL.
2487568150aSgwr 	 */
2497568150aSgwr 	if (aclp) {
2507568150aSgwr 		acl = acl_alloc(ACE_T);
2517568150aSgwr 		if (acl == NULL) {
2527568150aSgwr 			error = ENOMEM;
2537568150aSgwr 			goto out;
2547568150aSgwr 		}
2557568150aSgwr 	}
2567568150aSgwr 	error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp);
2577568150aSgwr 	if (error)
2587568150aSgwr 		goto out;
2597568150aSgwr 
2607568150aSgwr 	/* Success! */
2617568150aSgwr 	if (aclp) {
2627568150aSgwr 		*aclp = acl;
2637568150aSgwr 		acl = NULL;
2647568150aSgwr 	}
2657568150aSgwr 
2667568150aSgwr out:
2677568150aSgwr 	if (acl)
2687568150aSgwr 		acl_free(acl);
2697568150aSgwr 	smbfs_acl_free_sd(sd);
2707568150aSgwr 	return (error);
2717568150aSgwr }
2727568150aSgwr 
2737568150aSgwr /*
2747568150aSgwr  * Convenience function to Set security using a
2757568150aSgwr  * ZFS-style ACL (libsec acl, type=ACE_T)
2767568150aSgwr  * Intentionally similar to: facl_set(3SEC)
2777568150aSgwr  */
2787568150aSgwr int
smbfs_acl_set(int fd,acl_t * acl,uid_t uid,gid_t gid)2797568150aSgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid)
2807568150aSgwr {
281bd7c6f51SGordon Ross 	struct stat st;
2827568150aSgwr 	i_ntsd_t *sd = NULL;
2837568150aSgwr 	uint32_t selector;
2847568150aSgwr 	int error;
2857568150aSgwr 
286bd7c6f51SGordon Ross 	if (acl && acl->acl_type != ACE_T)
287bd7c6f51SGordon Ross 		return (EINVAL);
288bd7c6f51SGordon Ross 
2897568150aSgwr 	/*
2907568150aSgwr 	 * Which parts of the SD are being modified?
2917568150aSgwr 	 * XXX: Ditto comments above re. SACL.
2927568150aSgwr 	 */
2937568150aSgwr 	selector = 0;
2947568150aSgwr 	if (acl)
2957568150aSgwr 		selector |= DACL_SECURITY_INFORMATION;
2967568150aSgwr 	if (uid != (uid_t)-1)
2977568150aSgwr 		selector |= OWNER_SECURITY_INFORMATION;
2987568150aSgwr 	if (gid != (gid_t)-1)
2997568150aSgwr 		selector |= GROUP_SECURITY_INFORMATION;
3007568150aSgwr 	if (selector == 0)
3017568150aSgwr 		return (0);
3027568150aSgwr 
303bd7c6f51SGordon Ross 	if (uid == (uid_t)-1 || gid == (gid_t)-1) {
304bd7c6f51SGordon Ross 		/*
305bd7c6f51SGordon Ross 		 * If not setting owner or group, we need the
306bd7c6f51SGordon Ross 		 * current owner and group for translating
307bd7c6f51SGordon Ross 		 * references via owner@ or group@ ACEs.
308bd7c6f51SGordon Ross 		 */
309bd7c6f51SGordon Ross 		if (fstat(fd, &st) != 0)
310bd7c6f51SGordon Ross 			return (errno);
311bd7c6f51SGordon Ross 		if (uid == (uid_t)-1)
312bd7c6f51SGordon Ross 			uid = st.st_uid;
313bd7c6f51SGordon Ross 		if (gid == (gid_t)-1)
314bd7c6f51SGordon Ross 			gid = st.st_gid;
315bd7c6f51SGordon Ross 	}
3167568150aSgwr 
3177568150aSgwr 	/*
3187568150aSgwr 	 * Convert the ZFS ACL to an internal SD.
3197568150aSgwr 	 * Returns allocated data in sd
3207568150aSgwr 	 */
321bd7c6f51SGordon Ross 	error = smbfs_acl_zfs2sd(acl, uid, gid, selector, &sd);
3227568150aSgwr 	if (error == 0)
3237568150aSgwr 		error = smbfs_acl_setsd(fd, selector, sd);
3247568150aSgwr 
3257568150aSgwr 	smbfs_acl_free_sd(sd);
3267568150aSgwr 
3277568150aSgwr 	return (error);
3287568150aSgwr }
329