summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbfs
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libsmbfs')
-rw-r--r--usr/src/lib/libsmbfs/Makefile.com5
-rw-r--r--usr/src/lib/libsmbfs/netsmb/smbfs_acl.h92
-rw-r--r--usr/src/lib/libsmbfs/netsmb/smbfs_isec.h113
-rw-r--r--usr/src/lib/libsmbfs/smb/acl_api.c306
-rw-r--r--usr/src/lib/libsmbfs/smb/acl_conv.c932
-rw-r--r--usr/src/lib/libsmbfs/smb/acl_print.c121
-rw-r--r--usr/src/lib/libsmbfs/smb/mapfile-vers8
-rw-r--r--usr/src/lib/libsmbfs/smb/mbuf.c11
8 files changed, 1585 insertions, 3 deletions
diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com
index 76e2eac287..9ffc1634ef 100644
--- a/usr/src/lib/libsmbfs/Makefile.com
+++ b/usr/src/lib/libsmbfs/Makefile.com
@@ -32,6 +32,9 @@ VERS= .1
# leaving out: kiconv.o
OBJECTS=\
+ acl_api.o \
+ acl_conv.o \
+ acl_print.o \
charsets.o \
cfopt.o \
ctx.o \
@@ -66,7 +69,7 @@ $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
C99MODE= $(C99_ENABLE)
-LDLIBS += -lsocket -lnsl -lc -lkrb5
+LDLIBS += -lsocket -lnsl -lc -lkrb5 -lsec -lidmap
# normal warnings...
CFLAGS += $(CCVERBOSE)
diff --git a/usr/src/lib/libsmbfs/netsmb/smbfs_acl.h b/usr/src/lib/libsmbfs/netsmb/smbfs_acl.h
new file mode 100644
index 0000000000..dc8972e5cb
--- /dev/null
+++ b/usr/src/lib/libsmbfs/netsmb/smbfs_acl.h
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#ifndef _NETSMB_SMBFS_ACL_H
+#define _NETSMB_SMBFS_ACL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Get/set ACL via contracted interface in libsmbfs.
+ * The ACL is in the form used by libsec (type=ACE_T)
+ * but we need to carry the uid/gid info here too.
+ */
+
+#include <sys/acl.h>
+
+/*
+ * Get a ZFS-style acl from an FD opened in smbfs.
+ * Intentionally similar to: facl_get(3SEC)
+ *
+ * Allocates an acl_t via libsec. Free with: acl_free(3SEC)
+ * Get owner/group IDs too if ID pointers != NULL
+ */
+int smbfs_acl_get(int fd, acl_t **, uid_t *, gid_t *);
+
+/*
+ * Set a ZFS-style acl onto an FD opened in smbfs.
+ * Intentionally similar to: facl_set(3SEC)
+ *
+ * The acl_t must be of type ACE_T (from libsec).
+ * Set owner/group IDs too if ID values != -1
+ */
+int smbfs_acl_set(int fd, acl_t *, uid_t, gid_t);
+
+
+/*
+ * Slightly lower-level functions, allowing access to
+ * the raw Windows Security Descriptor (SD)
+ */
+typedef struct i_ntsd i_ntsd_t;
+
+/*
+ * Get an "internal form" SD from the FD (opened in smbfs).
+ * Allocates a hierarchy in isdp. Caller must free it via
+ * smbfs_acl_free_isd()
+ */
+int smbfs_acl_getsd(int fd, uint32_t, i_ntsd_t **);
+
+/*
+ * Set an "internal form" SD onto the FD (opened in smbfs).
+ */
+int smbfs_acl_setsd(int fd, uint32_t, i_ntsd_t *);
+
+/*
+ * Convert an internal SD to a ZFS-style ACL.
+ * Get uid/gid too if pointers != NULL.
+ */
+int smbfs_acl_sd2zfs(i_ntsd_t *, acl_t *, uid_t *, gid_t *);
+
+/*
+ * Convert an internal SD to a ZFS-style ACL.
+ * Include owner/group too if uid/gid != -1.
+ */
+int smbfs_acl_zfs2sd(acl_t *, uid_t, gid_t, i_ntsd_t **);
+
+void smbfs_acl_free_sd(i_ntsd_t *);
+void smbfs_acl_print_sd(FILE *, i_ntsd_t *);
+
+#endif /* _NETSMB_SMBFS_ACL_H */
diff --git a/usr/src/lib/libsmbfs/netsmb/smbfs_isec.h b/usr/src/lib/libsmbfs/netsmb/smbfs_isec.h
new file mode 100644
index 0000000000..f6b3555345
--- /dev/null
+++ b/usr/src/lib/libsmbfs/netsmb/smbfs_isec.h
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#ifndef _SMBFS_ISEC_H
+#define _SMBFS_ISEC_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Internal Security Descriptor (SD)
+ */
+
+#include <netsmb/smbfs_acl.h>
+
+/*
+ * Internal form of an NT SID
+ * Same as on the wire, but possibly byte-swapped.
+ */
+typedef struct i_ntsid {
+ uint8_t sid_revision;
+ uint8_t sid_subauthcount;
+ uint8_t sid_authority[6];
+ uint32_t sid_subauthvec[1]; /* actually len=subauthcount */
+} i_ntsid_t;
+#define I_SID_SIZE(sacnt) (8 + 4 * (sacnt))
+
+/*
+ * Internal form of an NT ACE
+ */
+typedef struct i_ntace {
+ uint8_t ace_type;
+ uint8_t ace_flags;
+ uint32_t ace_rights; /* generic, standard, specific, etc */
+ i_ntsid_t *ace_sid;
+} i_ntace_t;
+
+/*
+ * Internal form of an NT ACL (see sacl/dacl below)
+ */
+typedef struct i_ntacl {
+ uint8_t acl_revision; /* 0x02 observed with W2K */
+ uint16_t acl_acecount;
+ i_ntace_t *acl_acevec[1]; /* actually, len=acecount */
+} i_ntacl_t;
+
+/*
+ * Internal form of an NT Security Descriptor (SD)
+ */
+struct i_ntsd {
+ uint8_t sd_revision; /* 0x01 observed between W2K */
+ uint16_t sd_flags;
+ i_ntsid_t *sd_owner;
+ i_ntsid_t *sd_group;
+ i_ntacl_t *sd_sacl;
+ i_ntacl_t *sd_dacl;
+};
+
+
+/*
+ * Import a raw SD (mb chain) into "internal" form.
+ * (like "absolute" form per. NT docs)
+ * Returns allocated data in sdp
+ */
+int mb_get_ntsd(mbdata_t *mbp, i_ntsd_t **sdp);
+
+/*
+ * Export an "internal" SD into an raw SD (mb chain).
+ * (a.k.a "self-relative" form per. NT docs)
+ * Returns allocated mbchain in mbp.
+ */
+int mb_put_ntsd(mbdata_t *mbp, i_ntsd_t *sd);
+
+
+/*
+ * Get an SD via ioctl on FD (with "selector" bits),
+ * stroing the raw Windows SD in the mb chain mbp.
+ */
+int smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp);
+
+/*
+ * Set an SD via ioctl on FD (with "selector" bits),
+ * with a raw Windows SD from the chain mbp.
+ */
+int smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp);
+
+
+int smbfs_sid2str(i_ntsid_t *sid,
+ char *obuf, size_t olen, uint32_t *ridp);
+
+#endif /* _SMBFS_ISEC_H */
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);
+}
diff --git a/usr/src/lib/libsmbfs/smb/acl_conv.c b/usr/src/lib/libsmbfs/smb/acl_conv.c
new file mode 100644
index 0000000000..2073bf47f5
--- /dev/null
+++ b/usr/src/lib/libsmbfs/smb/acl_conv.c
@@ -0,0 +1,932 @@
+/*
+ * 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 support for smbfs
+ *
+ * May want to move some of this to usr/src/common
+ * and compile with the smbfs kmod too, once we
+ * implement VOP_GETSECATTR, VOP_SETSECATTR.
+ */
+
+#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 <string.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>
+
+#ifdef _KERNEL
+#define MALLOC(size) kmem_alloc(size, KM_SLEEP)
+#define FREESZ(p, sz) kmem_free(p, sz)
+#else /* _KERNEL */
+#define MALLOC(size) malloc(size)
+#ifndef lint
+#define FREESZ(p, sz) free(p)
+#else /* lint */
+/* ARGSUSED */
+static void
+FREESZ(void *p, size_t sz)
+{
+ free(p);
+}
+#endif /* lint */
+#endif /* _KERNEL */
+
+
+#define ERRCHK(expr) if ((error = expr) != 0) goto errout
+
+/*
+ * Security IDentifier (SID)
+ */
+static void
+ifree_sid(i_ntsid_t *sid)
+{
+ size_t sz;
+
+ if (sid == NULL)
+ return;
+
+ sz = I_SID_SIZE(sid->sid_subauthcount);
+ FREESZ(sid, sz);
+}
+
+static int
+mb_get_sid(mbdata_t *mbp, i_ntsid_t **sidp)
+{
+ i_ntsid_t *sid = NULL;
+ uint8_t revision, subauthcount;
+ uint32_t *subauthp;
+ size_t sidsz;
+ int error, i;
+
+ if ((error = mb_get_uint8(mbp, &revision)) != 0)
+ return (error);
+ if ((error = mb_get_uint8(mbp, &subauthcount)) != 0)
+ return (error);
+
+ sidsz = I_SID_SIZE(subauthcount);
+
+ if ((sid = MALLOC(sidsz)) == NULL)
+ return (ENOMEM);
+
+ bzero(sid, sidsz);
+ sid->sid_revision = revision;
+ sid->sid_subauthcount = subauthcount;
+ ERRCHK(mb_get_mem(mbp, (char *)sid->sid_authority, 6));
+
+ subauthp = &sid->sid_subauthvec[0];
+ for (i = 0; i < subauthcount; i++) {
+ ERRCHK(mb_get_uint32le(mbp, subauthp));
+ subauthp++;
+ }
+
+ /* Success! */
+ *sidp = sid;
+ return (0);
+
+errout:
+ ifree_sid(sid);
+ return (error);
+}
+
+static int
+mb_put_sid(mbdata_t *mbp, i_ntsid_t *sid)
+{
+ uint32_t *subauthp;
+ int error, i;
+
+ if (sid == NULL)
+ return (EINVAL);
+
+ ERRCHK(mb_put_uint8(mbp, sid->sid_revision));
+ ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount));
+ ERRCHK(mb_put_mem(mbp, (char *)sid->sid_authority, 6));
+
+ subauthp = &sid->sid_subauthvec[0];
+ for (i = 0; i < sid->sid_subauthcount; i++) {
+ ERRCHK(mb_put_uint32le(mbp, *subauthp));
+ subauthp++;
+ }
+
+ /* Success! */
+ return (0);
+
+errout:
+ return (error);
+}
+
+
+/*
+ * Access Control Entry (ACE)
+ */
+static void
+ifree_ace(i_ntace_t *ace)
+{
+ size_t sz;
+
+ if (ace == NULL)
+ return;
+
+ ifree_sid(ace->ace_sid);
+ FREESZ(ace, sizeof (*ace));
+}
+
+static int
+mb_get_ace(mbdata_t *mbp, i_ntace_t **acep)
+{
+ i_ntace_t *ace = NULL;
+ uint16_t ace_len;
+ int error;
+
+ if ((ace = MALLOC(sizeof (*ace))) == NULL)
+ return (ENOMEM);
+ bzero(ace, sizeof (*ace));
+
+ ERRCHK(mb_get_uint8(mbp, &ace->ace_type));
+ ERRCHK(mb_get_uint8(mbp, &ace->ace_flags));
+ ERRCHK(mb_get_uint16le(mbp, &ace_len));
+ ERRCHK(mb_get_uint32le(mbp, &ace->ace_rights));
+
+ ERRCHK(mb_get_sid(mbp, &ace->ace_sid));
+ /* XXX: consume any ace_len not used? */
+
+ /* Success! */
+ *acep = ace;
+ return (0);
+
+errout:
+ ifree_ace(ace);
+ return (error);
+}
+
+static int
+mb_put_ace(mbdata_t *mbp, i_ntace_t *ace)
+{
+ int cnt0, error;
+ char *ace_len_p;
+ uint16_t ace_len;
+
+ if (ace == NULL)
+ return (EINVAL);
+
+ cnt0 = mbp->mb_count;
+
+ ERRCHK(mb_put_uint8(mbp, ace->ace_type));
+ ERRCHK(mb_put_uint8(mbp, ace->ace_flags));
+ ERRCHK(mb_fit(mbp, 2, &ace_len_p));
+ ERRCHK(mb_put_uint32le(mbp, ace->ace_rights));
+
+ ERRCHK(mb_put_sid(mbp, ace->ace_sid));
+
+ ace_len = mbp->mb_count - cnt0;
+ /* LINTED */
+ setwle(ace_len_p, 0, ace_len);
+
+ /* Success! */
+ return (0);
+
+errout:
+ return (error);
+}
+
+
+/*
+ * Access Control List (ACL)
+ */
+
+/* Not an OTW structure, so size can be at our convenience. */
+#define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *))
+
+static void
+ifree_acl(i_ntacl_t *acl)
+{
+ i_ntace_t **acep;
+ size_t sz;
+ int i;
+
+ if (acl == NULL)
+ return;
+
+ acep = &acl->acl_acevec[0];
+ for (i = 0; i < acl->acl_acecount; i++) {
+ ifree_ace(*acep);
+ acep++;
+ }
+ sz = I_ACL_SIZE(acl->acl_acecount);
+ FREESZ(acl, sz);
+}
+
+static int
+mb_get_acl(mbdata_t *mbp, i_ntacl_t **aclp)
+{
+ i_ntacl_t *acl = NULL;
+ i_ntace_t **acep;
+ uint8_t revision;
+ uint16_t acl_len, acecount;
+ uint32_t *subauthp;
+ size_t aclsz;
+ int i, error;
+
+ if ((error = mb_get_uint8(mbp, &revision)) != 0)
+ return (error);
+ if ((error = mb_get_uint8(mbp, NULL)) != 0)
+ return (error);
+ if ((error = mb_get_uint16le(mbp, &acl_len)) != 0)
+ return (error);
+ if ((error = mb_get_uint16le(mbp, &acecount)) != 0)
+ return (error);
+ if ((error = mb_get_uint16(mbp, NULL)) != 0)
+ return (error);
+
+ aclsz = I_ACL_SIZE(acecount);
+ if ((acl = MALLOC(aclsz)) == NULL)
+ return (ENOMEM);
+ bzero(acl, aclsz);
+ acl->acl_revision = revision;
+ acl->acl_acecount = acecount;
+
+ acep = &acl->acl_acevec[0];
+ for (i = 0; i < acl->acl_acecount; i++) {
+ ERRCHK(mb_get_ace(mbp, acep));
+ acep++;
+ }
+ /* XXX: consume any acl_len not used? */
+
+ /* Success! */
+ *aclp = acl;
+ return (0);
+
+errout:
+ ifree_acl(acl);
+ return (error);
+}
+
+static int
+mb_put_acl(mbdata_t *mbp, i_ntacl_t *acl)
+{
+ i_ntace_t **acep;
+ uint8_t revision;
+ char *acl_len_p;
+ uint16_t acl_len;
+ uint32_t *subauthp;
+ size_t aclsz;
+ int i, cnt0, error;
+
+ cnt0 = mbp->mb_count;
+
+ ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
+ ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
+ ERRCHK(mb_fit(mbp, 2, &acl_len_p));
+ ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
+ ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
+
+ acep = &acl->acl_acevec[0];
+ for (i = 0; i < acl->acl_acecount; i++) {
+ ERRCHK(mb_put_ace(mbp, *acep));
+ acep++;
+ }
+
+ /* Fill in acl_len_p */
+ acl_len = mbp->mb_count - cnt0;
+ /* LINTED */
+ setwle(acl_len_p, 0, acl_len);
+
+ /* Success! */
+ return (0);
+
+errout:
+ return (error);
+}
+
+
+/*
+ * Security Descriptor
+ */
+void
+smbfs_acl_free_sd(i_ntsd_t *sd)
+{
+
+ if (sd == NULL)
+ return;
+
+ ifree_sid(sd->sd_owner);
+ ifree_sid(sd->sd_group);
+ ifree_acl(sd->sd_sacl);
+ ifree_acl(sd->sd_dacl);
+
+ FREESZ(sd, sizeof (*sd));
+}
+
+/*
+ * Import a raw SD (mb chain) into "internal" form.
+ * (like "absolute" form per. NT docs)
+ * Returns allocated data in sdp
+ *
+ * Note: does NOT consume all the mbp data, so the
+ * caller has to take care of that if necessary.
+ */
+int
+mb_get_ntsd(mbdata_t *mbp, i_ntsd_t **sdp)
+{
+ i_ntsd_t *sd = NULL;
+ mbdata_t top_mb, tmp_mb;
+ uint32_t owneroff, groupoff, sacloff, dacloff;
+ int error;
+
+ if ((sd = MALLOC(sizeof (*sd))) == NULL)
+ return (ENOMEM);
+ bzero(sd, sizeof (*sd));
+
+ /*
+ * Offsets below are relative to this point,
+ * so save the mbp state for use below.
+ */
+ top_mb = *mbp;
+
+ ERRCHK(mb_get_uint8(mbp, &sd->sd_revision));
+ ERRCHK(mb_get_uint8(mbp, NULL));
+ ERRCHK(mb_get_uint16le(mbp, &sd->sd_flags));
+ ERRCHK(mb_get_uint32le(mbp, &owneroff));
+ ERRCHK(mb_get_uint32le(mbp, &groupoff));
+ ERRCHK(mb_get_uint32le(mbp, &sacloff));
+ ERRCHK(mb_get_uint32le(mbp, &dacloff));
+
+ /*
+ * For each section make a temporary copy of the
+ * top_mb state, advance to the given offset, and
+ * pass that to the lower mb_get_xxx functions.
+ * These could be marshalled in any order, but
+ * are normally found in the order shown here.
+ */
+ if (sacloff) {
+ tmp_mb = top_mb;
+ mb_get_mem(&tmp_mb, NULL, sacloff);
+ ERRCHK(mb_get_acl(&tmp_mb, &sd->sd_sacl));
+ }
+ if (dacloff) {
+ tmp_mb = top_mb;
+ mb_get_mem(&tmp_mb, NULL, dacloff);
+ ERRCHK(mb_get_acl(&tmp_mb, &sd->sd_dacl));
+ }
+ if (owneroff) {
+ tmp_mb = top_mb;
+ mb_get_mem(&tmp_mb, NULL, owneroff);
+ ERRCHK(mb_get_sid(&tmp_mb, &sd->sd_owner));
+ }
+ if (groupoff) {
+ tmp_mb = top_mb;
+ mb_get_mem(&tmp_mb, NULL, groupoff);
+ ERRCHK(mb_get_sid(&tmp_mb, &sd->sd_group));
+ }
+
+ /* Success! */
+ *sdp = sd;
+ return (0);
+
+errout:
+ smbfs_acl_free_sd(sd);
+ return (error);
+}
+
+/*
+ * Export an "internal" SD into an raw SD (mb chain).
+ * (a.k.a "self-relative" form per. NT docs)
+ * Returns allocated mbchain in mbp.
+ */
+int
+mb_put_ntsd(mbdata_t *mbp, i_ntsd_t *sd)
+{
+ char *owneroffp, *groupoffp, *sacloffp, *dacloffp;
+ uint32_t owneroff, groupoff, sacloff, dacloff;
+ int cnt0, error;
+
+ cnt0 = mbp->mb_count;
+ owneroff = groupoff = sacloff = dacloff = 0;
+
+ ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
+ ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
+ ERRCHK(mb_put_uint16le(mbp, sd->sd_flags));
+ ERRCHK(mb_fit(mbp, 4, &owneroffp));
+ ERRCHK(mb_fit(mbp, 4, &groupoffp));
+ ERRCHK(mb_fit(mbp, 4, &sacloffp));
+ ERRCHK(mb_fit(mbp, 4, &dacloffp));
+
+ /*
+ * These could be marshalled in any order, but
+ * are normally found in the order shown here.
+ */
+ if (sd->sd_sacl) {
+ sacloff = mbp->mb_count - cnt0;
+ ERRCHK(mb_put_acl(mbp, sd->sd_sacl));
+ }
+ if (sd->sd_dacl) {
+ dacloff = mbp->mb_count - cnt0;
+ ERRCHK(mb_put_acl(mbp, sd->sd_dacl));
+ }
+ if (sd->sd_owner) {
+ owneroff = mbp->mb_count - cnt0;
+ ERRCHK(mb_put_sid(mbp, sd->sd_owner));
+ }
+ if (sd->sd_group) {
+ groupoff = mbp->mb_count - cnt0;
+ ERRCHK(mb_put_sid(mbp, sd->sd_group));
+ }
+
+ /* Fill in the offsets */
+ /* LINTED */
+ setdle(owneroffp, 0, owneroff);
+ /* LINTED */
+ setdle(groupoffp, 0, groupoff);
+ /* LINTED */
+ setdle(sacloffp, 0, sacloff);
+ /* LINTED */
+ setdle(dacloffp, 0, dacloff);
+
+ /* Success! */
+ return (0);
+
+errout:
+ return (error);
+}
+
+
+/*
+ * Helper functions for conversion between ZFS-style ACLs
+ * and Windows Security Descriptors.
+ */
+
+
+/*
+ * Convert an NT SID to a string. Optionally return the
+ * last sub-authority (or "relative ID" -- RID) in *ridp
+ * and truncate the output string after the domain part.
+ * If ridp==NULL, the output string is the whole SID,
+ * including both the domain and RID.
+ *
+ * Return length written, or -1 on error.
+ */
+int
+smbfs_sid2str(i_ntsid_t *sid,
+ char *obuf, size_t osz, uint32_t *ridp)
+{
+ char *s = obuf;
+ uint64_t auth = 0;
+ uint_t i, n;
+ uint32_t subs, *ip;
+
+ n = snprintf(s, osz, "S-%u", sid->sid_revision);
+ if (n > osz)
+ return (-1);
+ s += n; osz -= n;
+
+ for (i = 0; i < 6; i++)
+ auth = (auth << 8) | sid->sid_authority[i];
+ n = snprintf(s, osz, "-%llu", auth);
+ if (n > osz)
+ return (-1);
+ s += n; osz -= n;
+
+ subs = sid->sid_subauthcount;
+ if (subs < 1 || subs > 15)
+ return (-1);
+ if (ridp)
+ subs--;
+
+ ip = &sid->sid_subauthvec[0];
+ for (; subs; subs--, ip++) {
+ n = snprintf(s, osz, "-%u", *ip);
+ if (n > osz)
+ return (-1);
+ s += n; osz -= n;
+ }
+ if (ridp)
+ *ridp = *ip;
+
+ return (s - obuf);
+}
+
+/*
+ * Our interface to the idmap service.
+ */
+
+#ifdef _KERNEL
+#define I_GetPidBySid kidmap_batch_getpidbysid
+#define I_GetMappings kidmap_get_mappings
+#else /* _KERNEL */
+#define I_GetPidBySid idmap_get_pidbysid
+#define I_GetMappings idmap_get_mappings
+#endif /* _KERNEL */
+
+struct mapinfo {
+ uid_t mi_uid; /* or gid */
+ int mi_isuser;
+ idmap_stat mi_status;
+};
+
+/*
+ * A special value for mi_isuser (above) to indicate
+ * that the SID is the well-known "Everyone" (S-1-1-0).
+ * The idmap library only uses -1, 0, 1, so this value
+ * is arbitrary but must not overlap w/ idmap values.
+ * XXX: Could use a way for idmap to tell us when
+ * it recognizes this well-known SID.
+ */
+#define IS_WKSID_EVERYONE 11
+
+/*
+ * Build an idmap request. Cleanup is
+ * handled by the caller (error or not)
+ */
+static int
+mkrq_idmap_sid2ux(
+ idmap_get_handle_t *idmap_gh,
+ i_ntsid_t *sid,
+ struct mapinfo *mip)
+{
+ char sid_prefix[256];
+ uint32_t rid;
+ idmap_stat idms;
+
+ if (smbfs_sid2str(sid, sid_prefix, sizeof (sid_prefix), &rid) < 0)
+ return (EINVAL);
+
+ /*
+ * Give the "Everyone" group special treatment.
+ */
+ if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) {
+ /* This is "Everyone" */
+ mip->mi_uid = (uid_t)-1;
+ mip->mi_isuser = IS_WKSID_EVERYONE;
+ mip->mi_status = 0;
+ return (0);
+ }
+
+ idms = I_GetPidBySid(idmap_gh, sid_prefix, rid, 0,
+ &mip->mi_uid, &mip->mi_isuser, &mip->mi_status);
+ if (idms != IDMAP_SUCCESS)
+ return (EINVAL);
+
+ return (0);
+}
+
+static void
+ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo *mip)
+{
+ uint32_t zamask;
+ uint16_t zflags, ntflags;
+ uint8_t zatype = ntace->ace_type;
+
+ /*
+ * Translate NT ACE flags to ZFS ACE flags.
+ * The low four bits are the same, but not
+ * others: INHERITED_ACE_FLAG, etc.
+ */
+ ntflags = ntace->ace_flags;
+ zflags = 0;
+
+ if (ntflags & OBJECT_INHERIT_ACE_FLAG)
+ zflags |= ACE_FILE_INHERIT_ACE;
+ if (ntflags & CONTAINER_INHERIT_ACE_FLAG)
+ zflags |= ACE_DIRECTORY_INHERIT_ACE;
+ if (ntflags & NO_PROPAGATE_INHERIT_ACE_FLAG)
+ zflags |= ACE_NO_PROPAGATE_INHERIT_ACE;
+ if (ntflags & INHERIT_ONLY_ACE_FLAG)
+ zflags |= ACE_INHERIT_ONLY_ACE;
+ if (ntflags & INHERITED_ACE_FLAG)
+ zflags |= ACE_INHERITED_ACE;
+
+ if (ntflags & SUCCESSFUL_ACCESS_ACE_FLAG)
+ zflags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
+ if (ntflags & FAILED_ACCESS_ACE_FLAG)
+ zflags |= ACE_FAILED_ACCESS_ACE_FLAG;
+
+ /*
+ * Add the "ID type" flags to the ZFS ace flags.
+ * Would be nice if the idmap header defined some
+ * manifest constants for these "isuser" values.
+ */
+ switch (mip->mi_isuser) {
+ case IS_WKSID_EVERYONE:
+ zflags |= ACE_EVERYONE;
+ break;
+ case 0: /* it's a GID */
+ zflags |= ACE_IDENTIFIER_GROUP;
+ break;
+ default:
+ case 1: /* it's a UID */
+ break;
+ }
+
+ /*
+ * The access mask bits are the same, but
+ * mask off any bits we don't expect.
+ * Should not see any GENERIC_xxx flags,
+ * as those are only valid in requested
+ * access masks, not ACLs. But if we do,
+ * get those, silently clear them here.
+ */
+ zamask = ntace->ace_rights & ACE_ALL_PERMS;
+
+ /*
+ * Verify that it's a known ACE type.
+ * Only handle the types that appear in
+ * V2, V3, V4 ACLs for now. Avoid failing
+ * the whole conversion if we get unknown
+ * ace types, but convert them to something
+ * that will have no effect on access.
+ */
+ if (zatype > SYSTEM_ALARM_OBJECT_ACE_TYPE) {
+ zatype = ACCESS_ALLOWED_ACE_TYPE;
+ zamask = 0; /* harmless */
+ }
+
+ /*
+ * Fill in the ZFS-style ACE
+ */
+ zacep->a_who = mip->mi_uid; /* from ace_sid */
+ zacep->a_access_mask = zamask;
+ zacep->a_flags = zflags;
+ zacep->a_type = zatype;
+}
+
+/*
+ * Convert an internal SD to a ZFS-style ACL.
+ * Note optional args: vsa/acl, uidp, gidp.
+ */
+int
+smbfs_acl_sd2zfs(
+ i_ntsd_t *sd,
+#ifdef _KERNEL
+ vsecattr_t *acl_info,
+#else /* _KERNEL */
+ acl_t *acl_info,
+#endif /* _KERNEL */
+ uid_t *uidp, gid_t *gidp)
+{
+ struct mapinfo *mip, *mapinfo = NULL;
+ int error, i, mapcnt, zacecnt, zacl_size;
+ ace_t *zacep;
+ i_ntacl_t *ntacl;
+ i_ntace_t **ntacep;
+#ifndef _KERNEL
+ idmap_handle_t *idmap_h = NULL;
+#endif /* _KERNEL */
+ idmap_get_handle_t *idmap_gh = NULL;
+ idmap_stat idms;
+
+ /*
+ * sanity checks
+ */
+#ifndef _KERNEL
+ if (acl_info) {
+ if (acl_info->acl_type != ACE_T ||
+ acl_info->acl_aclp != NULL ||
+ acl_info->acl_entry_size != sizeof (ace_t))
+ return (EINVAL);
+ }
+#endif /* _KERNEL */
+
+ /*
+ * First, get all the SID mappings.
+ * How many?
+ */
+ mapcnt = 0;
+ if (sd->sd_owner)
+ mapcnt++;
+ if (sd->sd_group)
+ mapcnt++;
+ if (sd->sd_sacl)
+ mapcnt += sd->sd_sacl->acl_acecount;
+ if (sd->sd_dacl)
+ mapcnt += sd->sd_dacl->acl_acecount;
+ if (mapcnt == 0)
+ return (EINVAL);
+
+ mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
+ if (mapinfo == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
+ bzero(mapinfo, mapcnt * sizeof (*mapinfo));
+
+
+ /*
+ * Build our request to the idmap deamon.
+ */
+#ifdef _KERNEL
+ idmap_gh = kidmap_get_create(curproc->p_zone);
+#else /* _KERNEL */
+ idms = idmap_init(&idmap_h);
+ if (idms != IDMAP_SUCCESS) {
+ error = ENOTACTIVE;
+ goto errout;
+ }
+ idms = idmap_get_create(idmap_h, &idmap_gh);
+ if (idms != IDMAP_SUCCESS) {
+ error = ENOTACTIVE;
+ goto errout;
+ }
+#endif /* _KERNEL */
+
+ mip = mapinfo;
+ if (sd->sd_owner) {
+ error = mkrq_idmap_sid2ux(
+ idmap_gh, sd->sd_owner, mip);
+ if (error)
+ goto errout;
+ mip++;
+ }
+ if (sd->sd_group) {
+ error = mkrq_idmap_sid2ux(
+ idmap_gh, sd->sd_group, mip);
+ if (error)
+ goto errout;
+ mip++;
+ }
+ if (sd->sd_sacl) {
+ ntacl = sd->sd_sacl;
+ ntacep = &ntacl->acl_acevec[0];
+ for (i = 0; i < ntacl->acl_acecount; i++) {
+ error = mkrq_idmap_sid2ux(
+ idmap_gh, (*ntacep)->ace_sid, mip);
+ if (error)
+ goto errout;
+ ntacep++;
+ mip++;
+ }
+ }
+ if (sd->sd_dacl) {
+ ntacl = sd->sd_dacl;
+ ntacep = &ntacl->acl_acevec[0];
+ for (i = 0; i < ntacl->acl_acecount; i++) {
+ error = mkrq_idmap_sid2ux(
+ idmap_gh, (*ntacep)->ace_sid, mip);
+ if (error)
+ goto errout;
+ ntacep++;
+ mip++;
+ }
+ }
+
+ idms = I_GetMappings(idmap_gh);
+ if (idms != IDMAP_SUCCESS) {
+#ifdef DEBUG
+ printf("idmap_get_mappings: rc=%d\n", rc);
+#endif
+ /* creative error choice */
+ error = EIDRM;
+ goto errout;
+ }
+
+ /*
+ * With any luck, we now have Unix user/group IDs
+ * for every Windows SID in the security descriptor.
+ * The remaining work is just format conversion.
+ */
+ mip = mapinfo;
+ if (sd->sd_owner) {
+ if (uidp) {
+ if (mip->mi_isuser == 1)
+ *uidp = mip->mi_uid;
+ else
+ *uidp = (uid_t)-1;
+ }
+ mip++;
+ } else {
+ if (uidp)
+ *uidp = (uid_t)-1;
+ }
+ if (sd->sd_group) {
+ if (gidp) {
+ if (mip->mi_isuser == 0)
+ *gidp = (gid_t)mip->mi_uid;
+ else
+ *gidp = (gid_t)-1;
+ }
+ mip++;
+ } else {
+ if (gidp)
+ *gidp = (gid_t)-1;
+ }
+
+ if (acl_info == NULL) {
+ /* Caller only wanted uid/gid */
+ goto ok_out;
+ }
+
+ /*
+ * Build the ZFS-style ACL
+ */
+ zacecnt = 0;
+ if (sd->sd_sacl)
+ zacecnt += sd->sd_sacl->acl_acecount;
+ if (sd->sd_dacl)
+ zacecnt += sd->sd_dacl->acl_acecount;
+ zacl_size = zacecnt * sizeof (ace_t);
+ zacep = MALLOC(zacl_size);
+#ifdef _KERNEL
+ acl_info->vsa_aclentp = zacep;
+ acl_info->vsa_aclentsz = zacl_size;
+#else /* _KERNEL */
+ if (zacep == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
+ acl_info->acl_cnt = zacecnt;
+ acl_info->acl_aclp = zacep;
+#endif /* _KERNEL */
+
+ if (sd->sd_sacl) {
+ ntacl = sd->sd_sacl;
+ ntacep = &ntacl->acl_acevec[0];
+ for (i = 0; i < ntacl->acl_acecount; i++) {
+ ntace2zace(zacep, *ntacep, mip);
+ zacep++;
+ ntacep++;
+ mip++;
+ }
+ }
+ if (sd->sd_dacl) {
+ ntacl = sd->sd_dacl;
+ ntacep = &ntacl->acl_acevec[0];
+ for (i = 0; i < ntacl->acl_acecount; i++) {
+ ntace2zace(zacep, *ntacep, mip);
+ zacep++;
+ ntacep++;
+ mip++;
+ }
+ }
+
+ok_out:
+ error = 0;
+
+errout:
+ if (mapinfo)
+ FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
+
+ return (error);
+}
+
+
+/*
+ * Convert an internal SD to a ZFS-style ACL.
+ * Include owner/group too if uid/gid != -1.
+ * Note optional arg: vsa/acl
+ */
+int smbfs_acl_zfs2sd(
+#ifdef _KERNEL
+ vsecattr_t *vsa,
+#else /* _KERNEL */
+ acl_t *acl,
+#endif /* _KERNEL */
+ uid_t uid, gid_t gid,
+ i_ntsd_t **sdp)
+{
+ /* XXX - todo */
+ return (ENOSYS);
+}
diff --git a/usr/src/lib/libsmbfs/smb/acl_print.c b/usr/src/lib/libsmbfs/smb/acl_print.c
new file mode 100644
index 0000000000..9a1d51e320
--- /dev/null
+++ b/usr/src/lib/libsmbfs/smb/acl_print.c
@@ -0,0 +1,121 @@
+/*
+ * 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"
+
+/*
+ * Print an NT Security Descriptor (SD) and its sub-components.
+ */
+
+#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 <string.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>
+
+static void
+fprint_sid(FILE *fp, i_ntsid_t *sid)
+{
+ static char sidbuf[256];
+
+ if (sid == NULL) {
+ fprintf(fp, "(null)\n");
+ return;
+ }
+
+ if (smbfs_sid2str(sid, sidbuf, sizeof (sidbuf), NULL) < 0)
+ fprintf(fp, "(error)\n");
+ else
+ fprintf(fp, "%s\n", sidbuf);
+}
+
+static void
+fprint_ntace(FILE *fp, i_ntace_t *ace)
+{
+ if (ace == NULL) {
+ fprintf(fp, " (null)\n");
+ return;
+ }
+
+ /* ACEs are always printed in a list, so indent by 2. */
+ fprintf(fp, " ace_type=%d ace_flags=0x%x ace_rights=0x%x\n",
+ ace->ace_type, ace->ace_flags, ace->ace_rights);
+ /* Show the SID as a "continuation" line. */
+ fprintf(fp, " ace_sid: ");
+ fprint_sid(fp, ace->ace_sid);
+}
+
+static void
+fprint_ntacl(FILE *fp, i_ntacl_t *acl)
+{
+ int i;
+
+ if (acl == NULL) {
+ fprintf(fp, "(null)\n");
+ return;
+ }
+
+ fprintf(fp, "acl_rev=%d acl_acecount=%d\n",
+ acl->acl_revision, acl->acl_acecount);
+ for (i = 0; i < acl->acl_acecount; i++)
+ fprint_ntace(fp, acl->acl_acevec[i]);
+}
+
+void
+smbfs_acl_print_sd(FILE *fp, i_ntsd_t *sd)
+{
+
+ fprintf(fp, "sd_rev=%d, flags=0x%x\n",
+ sd->sd_revision, sd->sd_flags);
+ fprintf(fp, "owner: ");
+ fprint_sid(fp, sd->sd_owner);
+ fprintf(fp, "group: ");
+ fprint_sid(fp, sd->sd_group);
+ fprintf(fp, "sacl: ");
+ fprint_ntacl(fp, sd->sd_sacl);
+ fprintf(fp, "dacl: ");
+ fprint_ntacl(fp, sd->sd_dacl);
+}
diff --git a/usr/src/lib/libsmbfs/smb/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers
index 1dadbbe825..f8f38ba6b0 100644
--- a/usr/src/lib/libsmbfs/smb/mapfile-vers
+++ b/usr/src/lib/libsmbfs/smb/mapfile-vers
@@ -60,6 +60,14 @@ SUNWprivate_1.0 {
smb_read;
smb_write;
smb_verbose;
+ smbfs_acl_free_sd;
+ smbfs_acl_get;
+ smbfs_acl_getsd;
+ smbfs_acl_print_sd;
+ smbfs_acl_sd2zfs;
+ smbfs_acl_set;
+ smbfs_acl_setsd;
+ smbfs_acl_zfs2sd;
smbfs_default_dom_usr;
smbfs_keychain_add;
smbfs_keychain_chk;
diff --git a/usr/src/lib/libsmbfs/smb/mbuf.c b/usr/src/lib/libsmbfs/smb/mbuf.c
index f03c4fedc3..6f08ce1def 100644
--- a/usr/src/lib/libsmbfs/smb/mbuf.c
+++ b/usr/src/lib/libsmbfs/smb/mbuf.c
@@ -42,6 +42,7 @@
#include <string.h>
#include <strings.h>
#include <libintl.h>
+#include <assert.h>
#include <netsmb/smb.h>
#include <netsmb/smb_lib.h>
@@ -58,6 +59,8 @@ m_get(size_t len, struct mbuf **mpp)
{
struct mbuf *m;
+ assert(len < 0x100000); /* sanity */
+
len = M_ALIGN(len);
if (len < M_MINSIZE)
len = M_MINSIZE;
@@ -163,10 +166,13 @@ int
m_getm(struct mbuf *top, size_t len, struct mbuf **mpp)
{
struct mbuf *m, *mp;
- int error;
+ int error, ts;
for (mp = top; ; mp = mp->m_next) {
- len -= M_TRAILINGSPACE(mp);
+ ts = M_TRAILINGSPACE(mp);
+ if (len <= ts)
+ goto out;
+ len -= ts;
if (mp->m_next == NULL)
break;
@@ -176,6 +182,7 @@ m_getm(struct mbuf *top, size_t len, struct mbuf **mpp)
return (error);
mp->m_next = m;
}
+out:
*mpp = top;
return (0);
}