xref: /onnv-gate/usr/src/lib/libsmbfs/smb/acl_api.c (revision 11564)
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*11564SGordon.Ross@Sun.COM  * Copyright 2010 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 
5210023SGordon.Ross@Sun.COM #include <netsmb/smb.h>
536711Sgwr #include <netsmb/smb_lib.h>
546711Sgwr #include <netsmb/smbfs_acl.h>
5510023SGordon.Ross@Sun.COM 
5611332SGordon.Ross@Sun.COM #include "smbfs_ntacl.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 
8111332SGordon.Ross@Sun.COM 	error = mb_init_sz(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 		 */
16011332SGordon.Ross@Sun.COM 		error = md_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;
17711332SGordon.Ross@Sun.COM 	error = mb_init_sz(mbp, MAX_RAW_SD_SIZE);
17811332SGordon.Ross@Sun.COM 	if (error)
17911332SGordon.Ross@Sun.COM 		return (error);
1806711Sgwr 
1816711Sgwr 	/*
1826711Sgwr 	 * Export the "internal" SD into an mb chain.
1836711Sgwr 	 * (a.k.a "self-relative" form per. NT docs)
1846711Sgwr 	 * Returns allocated mbchain in mbp.
1856711Sgwr 	 */
1866711Sgwr 	error = mb_put_ntsd(mbp, sd);
1876711Sgwr 	if (error == 0) {
1886711Sgwr 		/*
1896711Sgwr 		 * Set the raw Windows SD via ioctl.
1906711Sgwr 		 */
1916711Sgwr 		error = smbfs_acl_iocset(fd, selector, mbp);
1926711Sgwr 	}
1936711Sgwr 
1946711Sgwr 	mb_done(mbp);
1956711Sgwr 
1966711Sgwr 	return (error);
1976711Sgwr }
1986711Sgwr 
1996711Sgwr 
2006711Sgwr 
2016711Sgwr /*
2026711Sgwr  * Convenience function to Get security using a
2036711Sgwr  * ZFS-style ACL (libsec acl, type=ACE_T)
2046711Sgwr  * Intentionally similar to: facl_get(3SEC)
2056711Sgwr  */
2066711Sgwr int
2076711Sgwr smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp)
2086711Sgwr {
2096711Sgwr 	i_ntsd_t *sd = NULL;
2106711Sgwr 	acl_t *acl = NULL;
2116711Sgwr 	uint32_t selector;
2126711Sgwr 	int error;
2136711Sgwr 
2146711Sgwr 	/*
2156711Sgwr 	 * Which parts of the SD are being requested?
2166711Sgwr 	 * XXX: Should we request the SACL too?  If so,
2176711Sgwr 	 * might that cause this access to be denied?
2186711Sgwr 	 * Or maybe: if we get access denied, try the
2196711Sgwr 	 * open/fetch again without the SACL bit.
2206711Sgwr 	 */
2216711Sgwr 	selector = 0;
2226711Sgwr 	if (aclp)
2236711Sgwr 		selector |= DACL_SECURITY_INFORMATION;
2246711Sgwr 	if (uidp)
2256711Sgwr 		selector |= OWNER_SECURITY_INFORMATION;
2266711Sgwr 	if (gidp)
2276711Sgwr 		selector |= GROUP_SECURITY_INFORMATION;
2286711Sgwr 
2296711Sgwr 	if (selector == 0)
2306711Sgwr 		return (0);
2316711Sgwr 
2326711Sgwr 	/*
2336711Sgwr 	 * Get the Windows SD via ioctl, in
2346711Sgwr 	 * "internal" (absolute) form.
2356711Sgwr 	 */
2366711Sgwr 	error = smbfs_acl_getsd(fd, selector, &sd);
2376711Sgwr 	if (error)
2386711Sgwr 		return (error);
2396711Sgwr 	/* Note: sd now holds allocated data. */
2406711Sgwr 
2416711Sgwr 	/*
2426711Sgwr 	 * Convert the internal SD to a ZFS ACL.
2436711Sgwr 	 * Get uid/gid too if pointers != NULL.
2446711Sgwr 	 */
2456711Sgwr 	if (aclp) {
2466711Sgwr 		acl = acl_alloc(ACE_T);
2476711Sgwr 		if (acl == NULL) {
2486711Sgwr 			error = ENOMEM;
2496711Sgwr 			goto out;
2506711Sgwr 		}
2516711Sgwr 	}
2526711Sgwr 	error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp);
2536711Sgwr 	if (error)
2546711Sgwr 		goto out;
2556711Sgwr 
2566711Sgwr 	/* Success! */
2576711Sgwr 	if (aclp) {
2586711Sgwr 		*aclp = acl;
2596711Sgwr 		acl = NULL;
2606711Sgwr 	}
2616711Sgwr 
2626711Sgwr out:
2636711Sgwr 	if (acl)
2646711Sgwr 		acl_free(acl);
2656711Sgwr 	smbfs_acl_free_sd(sd);
2666711Sgwr 	return (error);
2676711Sgwr }
2686711Sgwr 
2696711Sgwr /*
2706711Sgwr  * Convenience function to Set security using a
2716711Sgwr  * ZFS-style ACL (libsec acl, type=ACE_T)
2726711Sgwr  * Intentionally similar to: facl_set(3SEC)
2736711Sgwr  */
2746711Sgwr int
2756711Sgwr smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid)
2766711Sgwr {
277*11564SGordon.Ross@Sun.COM 	struct stat st;
2786711Sgwr 	i_ntsd_t *sd = NULL;
2796711Sgwr 	uint32_t selector;
2806711Sgwr 	int error;
2816711Sgwr 
282*11564SGordon.Ross@Sun.COM 	if (acl && acl->acl_type != ACE_T)
283*11564SGordon.Ross@Sun.COM 		return (EINVAL);
284*11564SGordon.Ross@Sun.COM 
2856711Sgwr 	/*
2866711Sgwr 	 * Which parts of the SD are being modified?
2876711Sgwr 	 * XXX: Ditto comments above re. SACL.
2886711Sgwr 	 */
2896711Sgwr 	selector = 0;
2906711Sgwr 	if (acl)
2916711Sgwr 		selector |= DACL_SECURITY_INFORMATION;
2926711Sgwr 	if (uid != (uid_t)-1)
2936711Sgwr 		selector |= OWNER_SECURITY_INFORMATION;
2946711Sgwr 	if (gid != (gid_t)-1)
2956711Sgwr 		selector |= GROUP_SECURITY_INFORMATION;
2966711Sgwr 	if (selector == 0)
2976711Sgwr 		return (0);
2986711Sgwr 
299*11564SGordon.Ross@Sun.COM 	if (uid == (uid_t)-1 || gid == (gid_t)-1) {
300*11564SGordon.Ross@Sun.COM 		/*
301*11564SGordon.Ross@Sun.COM 		 * If not setting owner or group, we need the
302*11564SGordon.Ross@Sun.COM 		 * current owner and group for translating
303*11564SGordon.Ross@Sun.COM 		 * references via owner@ or group@ ACEs.
304*11564SGordon.Ross@Sun.COM 		 */
305*11564SGordon.Ross@Sun.COM 		if (fstat(fd, &st) != 0)
306*11564SGordon.Ross@Sun.COM 			return (errno);
307*11564SGordon.Ross@Sun.COM 		if (uid == (uid_t)-1)
308*11564SGordon.Ross@Sun.COM 			uid = st.st_uid;
309*11564SGordon.Ross@Sun.COM 		if (gid == (gid_t)-1)
310*11564SGordon.Ross@Sun.COM 			gid = st.st_gid;
311*11564SGordon.Ross@Sun.COM 	}
3126711Sgwr 
3136711Sgwr 	/*
3146711Sgwr 	 * Convert the ZFS ACL to an internal SD.
3156711Sgwr 	 * Returns allocated data in sd
3166711Sgwr 	 */
317*11564SGordon.Ross@Sun.COM 	error = smbfs_acl_zfs2sd(acl, uid, gid, selector, &sd);
3186711Sgwr 	if (error == 0)
3196711Sgwr 		error = smbfs_acl_setsd(fd, selector, sd);
3206711Sgwr 
3216711Sgwr 	smbfs_acl_free_sd(sd);
3226711Sgwr 
3236711Sgwr 	return (error);
3246711Sgwr }
325