summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbfs/smb/acl_api.c
diff options
context:
space:
mode:
authorgwr <none@none>2008-05-26 11:27:50 -0700
committergwr <none@none>2008-05-26 11:27:50 -0700
commit7568150a58e78021968b6c22bc28e9787b33496a (patch)
tree834cd3661c8d4ef83077b9f4d0b54a3d25f6767c /usr/src/lib/libsmbfs/smb/acl_api.c
parent664d603cda9e909161e63d9ac5ff4724dd2a4852 (diff)
downloadillumos-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.c306
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);
+}