diff options
author | gwr <none@none> | 2008-05-26 11:27:50 -0700 |
---|---|---|
committer | gwr <none@none> | 2008-05-26 11:27:50 -0700 |
commit | 7568150a58e78021968b6c22bc28e9787b33496a (patch) | |
tree | 834cd3661c8d4ef83077b9f4d0b54a3d25f6767c /usr/src/lib/libsmbfs/smb/acl_api.c | |
parent | 664d603cda9e909161e63d9ac5ff4724dd2a4852 (diff) | |
download | illumos-gate-7568150a58e78021968b6c22bc28e9787b33496a.tar.gz |
6647735 Need fetch/store ACL support
6707025 The owner and group id display should be unsigned
Diffstat (limited to 'usr/src/lib/libsmbfs/smb/acl_api.c')
-rw-r--r-- | usr/src/lib/libsmbfs/smb/acl_api.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/usr/src/lib/libsmbfs/smb/acl_api.c b/usr/src/lib/libsmbfs/smb/acl_api.c new file mode 100644 index 0000000000..2dc024e086 --- /dev/null +++ b/usr/src/lib/libsmbfs/smb/acl_api.c @@ -0,0 +1,306 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * ACL API for smbfs + */ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/cred.h> +#include <sys/cmn_err.h> +#include <sys/kmem.h> +#include <sys/sunddi.h> +#include <sys/acl.h> +#include <sys/vnode.h> +#include <sys/vfs.h> +#include <sys/byteorder.h> + +#include <errno.h> +#include <stdio.h> +#include <strings.h> +#include <unistd.h> + +#include <umem.h> +#include <idmap.h> + +#include <sys/fs/smbfs_ioctl.h> + +#include <netsmb/smb_lib.h> +#include <netsmb/smbfs_acl.h> +#include <netsmb/smbfs_isec.h> + +/* Sanity check SD sizes */ +#define MAX_RAW_SD_SIZE 32768 + +/* XXX: acl_common.h */ +acl_t *acl_alloc(enum acl_type); +void acl_free(acl_t *); + + +/* + * Get/set a Windows security descriptor (SD) + * using the (private) smbfs ioctl mechanism. + * Note: Get allocates mbp->mb_top + */ + +/* ARGSUSED */ +int +smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) +{ + ioc_sdbuf_t iocb; + struct mbuf *m; + int error; + + error = mb_init(mbp, MAX_RAW_SD_SIZE); + if (error) + return (error); + + m = mbp->mb_top; + iocb.addr = mtod(m, uintptr_t); + iocb.alloc = m->m_maxlen; + iocb.used = 0; + iocb.selector = selector; + + /* + * This does the OTW Get. + */ + if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { + error = errno; + goto errout; + } + + m->m_len = iocb.used; + return (0); + +errout: + mb_done(mbp); + return (error); +} + +/* ARGSUSED */ +int +smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) +{ + ioc_sdbuf_t iocb; + struct mbuf *m; + int error; + + /* Make the data contiguous. */ + error = m_lineup(mbp->mb_top, &m); + if (error) + return (error); + + if (mbp->mb_top != m) + mb_initm(mbp, m); + + iocb.addr = mtod(m, uintptr_t); + iocb.alloc = m->m_maxlen; + iocb.used = m->m_len; + iocb.selector = selector; + + /* + * This does the OTW Set. + */ + if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) + error = errno; + + return (error); +} + +/* + * Get an NT SD from the open file via ioctl. + */ +int +smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp) +{ + mbdata_t *mbp, mb_store; + int error; + + mbp = &mb_store; + bzero(mbp, sizeof (*mbp)); + + /* + * Get the raw Windows SD via ioctl. + * Returns allocated mbchain in mbp. + */ + error = smbfs_acl_iocget(fd, selector, mbp); + if (error == 0) { + /* + * Import the raw SD into "internal" form. + * (like "absolute" form per. NT docs) + * Returns allocated data in sdp + */ + error = mb_get_ntsd(mbp, sdp); + } + + mb_done(mbp); + return (error); +} + +/* + * Set an NT SD onto the open file via ioctl. + */ +int +smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd) +{ + mbdata_t *mbp, mb_store; + int error; + + mbp = &mb_store; + mb_init(mbp, M_MINSIZE); + + /* + * Export the "internal" SD into an mb chain. + * (a.k.a "self-relative" form per. NT docs) + * Returns allocated mbchain in mbp. + */ + error = mb_put_ntsd(mbp, sd); + if (error == 0) { + /* + * Set the raw Windows SD via ioctl. + */ + error = smbfs_acl_iocset(fd, selector, mbp); + } + + mb_done(mbp); + + return (error); +} + + + +/* + * Convenience function to Get security using a + * ZFS-style ACL (libsec acl, type=ACE_T) + * Intentionally similar to: facl_get(3SEC) + */ +int +smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp) +{ + i_ntsd_t *sd = NULL; + acl_t *acl = NULL; + uint32_t selector; + int error; + + /* + * Which parts of the SD are being requested? + * XXX: Should we request the SACL too? If so, + * might that cause this access to be denied? + * Or maybe: if we get access denied, try the + * open/fetch again without the SACL bit. + */ + selector = 0; + if (aclp) + selector |= DACL_SECURITY_INFORMATION; + if (uidp) + selector |= OWNER_SECURITY_INFORMATION; + if (gidp) + selector |= GROUP_SECURITY_INFORMATION; + + if (selector == 0) + return (0); + + /* + * Get the Windows SD via ioctl, in + * "internal" (absolute) form. + */ + error = smbfs_acl_getsd(fd, selector, &sd); + if (error) + return (error); + /* Note: sd now holds allocated data. */ + + /* + * Convert the internal SD to a ZFS ACL. + * Get uid/gid too if pointers != NULL. + */ + if (aclp) { + acl = acl_alloc(ACE_T); + if (acl == NULL) { + error = ENOMEM; + goto out; + } + } + error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp); + if (error) + goto out; + + /* Success! */ + if (aclp) { + *aclp = acl; + acl = NULL; + } + +out: + if (acl) + acl_free(acl); + smbfs_acl_free_sd(sd); + return (error); +} + +/* + * Convenience function to Set security using a + * ZFS-style ACL (libsec acl, type=ACE_T) + * Intentionally similar to: facl_set(3SEC) + */ +int +smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid) +{ + i_ntsd_t *sd = NULL; + uint32_t selector; + int error; + + /* + * Which parts of the SD are being modified? + * XXX: Ditto comments above re. SACL. + */ + selector = 0; + if (acl) + selector |= DACL_SECURITY_INFORMATION; + if (uid != (uid_t)-1) + selector |= OWNER_SECURITY_INFORMATION; + if (gid != (gid_t)-1) + selector |= GROUP_SECURITY_INFORMATION; + if (selector == 0) + return (0); + + if (acl && acl->acl_type != ACE_T) + return (EINVAL); + + /* + * Convert the ZFS ACL to an internal SD. + * Returns allocated data in sd + */ + error = smbfs_acl_zfs2sd(acl, uid, gid, &sd); + if (error == 0) + error = smbfs_acl_setsd(fd, selector, sd); + + smbfs_acl_free_sd(sd); + + return (error); +} |