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