diff options
Diffstat (limited to 'usr/src')
21 files changed, 2670 insertions, 102 deletions
diff --git a/usr/src/cmd/fs.d/smbclnt/Makefile b/usr/src/cmd/fs.d/smbclnt/Makefile index 2f52565016..8845071f42 100644 --- a/usr/src/cmd/fs.d/smbclnt/Makefile +++ b/usr/src/cmd/fs.d/smbclnt/Makefile @@ -32,7 +32,7 @@ include $(SRC)/Makefile.master SUBDIRS_CATALOG= smbutil mount umount -SUBDIRS= $(SUBDIRS_CATALOG) svc +SUBDIRS= $(SUBDIRS_CATALOG) lsacl svc # for messaging catalog files # diff --git a/usr/src/cmd/fs.d/smbclnt/lsacl/Makefile b/usr/src/cmd/fs.d/smbclnt/lsacl/Makefile new file mode 100644 index 0000000000..22ce8510c0 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/lsacl/Makefile @@ -0,0 +1,55 @@ +# +# 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. +# +# ident "%Z%%M% %I% %E% SMI" +# + +FSTYPE= smbfs +LIBPROG= lsacl +ROOTFS_PROG= $(LIBPROG) + +include ../../Makefile.fstype + +OBJS= $(LIBPROG).o +SRCS= $(LIBPROG).c $(FSLIBSRC) + +LDLIBS += -lsmbfs -lsec + +CFLAGS += $(CCVERBOSE) +C99MODE= $(C99_ENABLE) +CPPFLAGS += -I$(SRC)/lib/libsmbfs \ + -I$(SRC)/uts/common/smbclnt -I$(SRC)/uts/common + +CLOBBERFILES += $(LIBPROG) + +all: $(ROOTFS_PROG) + +install: $(ROOTLIBFSTYPEPROG) + +lint: lint_SRCS + +clean: + $(RM) $(OBJS) + +.KEEP_STATE: diff --git a/usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c b/usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c new file mode 100644 index 0000000000..9f73f8eb1e --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c @@ -0,0 +1,120 @@ +/* + * 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" + +/* + * This is the smbfs/lsacl command. + * (just for testing - not installed) + */ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <sys/acl.h> + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <netsmb/smb_lib.h> +#include <netsmb/smbfs_acl.h> + +char *progname; + +extern void acl_printacl(acl_t *, int, int); + + +void +usage(void) +{ + fprintf(stderr, "usage: %s file\n", progname); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct acl_info *acl; + uid_t uid; + gid_t gid; + int error, fd; + i_ntsd_t *sd; + + progname = argv[0]; + + if (argc < 2) + usage(); + + fd = open(argv[1], O_RDONLY, 0); + if (fd < 0) { + perror(argv[1]); + exit(1); + } + + /* First, get the raw NT SD. */ + error = smbfs_acl_getsd(fd, 7, &sd); + if (error) { + fprintf(stderr, "getsd: %s\n", + smb_strerror(error)); + exit(1); + } + + /* + * Print it first in Windows form. This way, + * if any of the conversion has problems, + * one can try mapping each SID by hand, i.e.: + * idmap show sid:S-1-xxx-yyy-zzz + */ + printf("CIFS security data:\n"); + smbfs_acl_print_sd(stdout, sd); + printf("\n"); + + /* + * Get it again as a ZFS-style ACL (ACE_T) + */ + error = smbfs_acl_get(fd, &acl, &uid, &gid); + if (error) { + fprintf(stderr, "getacl: %s\n", + smb_strerror(error)); + exit(1); + } + printf("Solaris security data:\n"); + if (uid == (uid_t)-1) + printf("owner: -1\n"); + else + printf("owner: %u\n", uid); + if (gid == (gid_t)-1) + printf("group: -1\n"); + else + printf("group: %u\n", gid); + acl_printacl(acl, 80, 0); + printf("\n"); + + return (0); +} 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); } diff --git a/usr/src/pkgdefs/etc/exception_list_i386 b/usr/src/pkgdefs/etc/exception_list_i386 index c05834c0ea..512ba1105a 100644 --- a/usr/src/pkgdefs/etc/exception_list_i386 +++ b/usr/src/pkgdefs/etc/exception_list_i386 @@ -1086,3 +1086,7 @@ usr/lib/amd64/libsmbfs.so i386 usr/lib/llib-lsmbfs i386 usr/lib/llib-lsmbfs.ln i386 usr/lib/amd64/llib-lsmbfs.ln i386 +# +# demo & test program for smbfs (private) ACL support +# +usr/lib/fs/smbfs/lsacl i386 diff --git a/usr/src/pkgdefs/etc/exception_list_sparc b/usr/src/pkgdefs/etc/exception_list_sparc index 8693457eda..85e8077e70 100644 --- a/usr/src/pkgdefs/etc/exception_list_sparc +++ b/usr/src/pkgdefs/etc/exception_list_sparc @@ -1167,3 +1167,7 @@ usr/lib/sparcv9/libsmbfs.so sparc usr/lib/llib-lsmbfs sparc usr/lib/llib-lsmbfs.ln sparc usr/lib/sparcv9/llib-lsmbfs.ln sparc +# +# demo & test program for smbfs (private) ACL support +# +usr/lib/fs/smbfs/lsacl sparc diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 0fb6a5010f..a5944235c1 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -1043,9 +1043,10 @@ NSMB_OBJS += smb_conn.o smb_crypt.o smb_dev.o smb_iod.o \ smb_rq.o smb_smb.o smb_tran.o smb_trantcp.o \ smb_usr.o smb_subrs.o subr_mchain.o smb_pass.o -SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \ - smbfs_client.o smbfs_io.o smbfs_smb.o \ - smbfs_subr.o smbfs_subr2.o smbfs_rwlock.o +SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \ + smbfs_acl.o smbfs_client.o smbfs_io.o \ + smbfs_smb.o smbfs_subr.o smbfs_subr2.o \ + smbfs_rwlock.o # # LVM modules diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c index 1115e6fc69..a7834f65e4 100644 --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c @@ -907,9 +907,6 @@ smb_nt_reply(struct smb_ntrq *ntp) return (error ? error : error2); } -int md_get_mbuf(struct mdchain *mdp, int size, mblk_t **ret); -int mb_put_mbuf(struct mbchain *mbp, mblk_t *m); - /* * Perform a full round of TRANS2 request */ diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c new file mode 100644 index 0000000000..88665cfd1b --- /dev/null +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c @@ -0,0 +1,446 @@ +/* + * 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 + */ + +#include <sys/systm.h> /* bcopy, ... */ +#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 <netsmb/smb_osdep.h> +#include <netsmb/smb.h> +#include <netsmb/smb_conn.h> +#include <netsmb/smb_subr.h> +#include <netsmb/mchain.h> + +#include <smbfs/smbfs.h> +#include <smbfs/smbfs_node.h> +#include <smbfs/smbfs_subr.h> + +#include <sys/fs/smbfs_ioctl.h> +#include <fs/fs_subr.h> + +/* Sanity check SD sizes */ +#define MAX_RAW_SD_SIZE 32768 +#define SMALL_SD_SIZE 1024 + +#undef ACL_SUPPORT /* not yet */ + + +/* + * smbfs_getsd(), smbfs_setsd() are common functions used by + * both ioctl get/set ACL and VOP_GETSECATTR, VOP_SETSECATTR. + * Handles required rights, tmpopen/tmpclose. + * + * Note: smbfs_getsd allocates and returns an mblk chain, + * which the caller must free. + */ +int +smbfs_getsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr) +{ + struct smb_cred scred; + int error, cerror; + smbmntinfo_t *smi; + smbnode_t *np; + u_int16_t fid = SMB_FID_UNUSED; + uint32_t sdlen = SMALL_SD_SIZE; + uint32_t rights = STD_RIGHT_READ_CONTROL_ACCESS; + + if (selector & SACL_SECURITY_INFORMATION) + rights |= SEC_RIGHT_SYSTEM_SECURITY; + + np = VTOSMB(vp); + smi = VTOSMI(vp); + + /* Shared lock for (possible) n_fid use. */ + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) + return (EINTR); + smb_credinit(&scred, curproc, cr); + + error = smbfs_smb_tmpopen(np, rights, &scred, &fid); + if (error) + goto out; + +again: + /* + * This does the OTW Get + */ + error = smbfs_smb_getsec_m(smi->smi_share, fid, + &scred, selector, mp, &sdlen); + /* + * Server may give us an error indicating that we + * need a larger data buffer to receive the SD, + * and the size we'll need. Use the given size, + * but only after a sanity check. + * + * Let's check for specific error values here. + * The NT error is: STATUS_BUFFER_TOO_SMALL, + * or with old error codes, one of these: + * ERRSRV/ERRnoroom, ERRDOS/122, ERRDOS/111 + * Those are mapped to: EMOREDATA, which is + * later converted to E2BIG. + */ + if (error == E2BIG && + sdlen > SMALL_SD_SIZE && + sdlen <= MAX_RAW_SD_SIZE) + goto again; + + cerror = smbfs_smb_tmpclose(np, fid, &scred); + if (cerror) + SMBERROR("error %d closing file %s\n", + cerror, np->n_rpath); + +out: + smb_credrele(&scred); + smbfs_rw_exit(&np->r_lkserlock); + + return (error); +} + +int +smbfs_setsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr) +{ + struct smb_cred scred; + int error, cerror; + smbmntinfo_t *smi; + smbnode_t *np; + uint32_t rights; + u_int16_t fid = SMB_FID_UNUSED; + + np = VTOSMB(vp); + smi = VTOSMI(vp); + + /* + * Which parts of the SD are we setting? + * What rights do we need for that? + */ + if (selector == 0) + return (0); + rights = 0; + if (selector & (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION)) + rights |= STD_RIGHT_WRITE_OWNER_ACCESS; + if (selector & DACL_SECURITY_INFORMATION) + rights |= STD_RIGHT_WRITE_DAC_ACCESS; + if (selector & SACL_SECURITY_INFORMATION) + rights |= SEC_RIGHT_SYSTEM_SECURITY; + + /* Shared lock for (possible) n_fid use. */ + if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) + return (EINTR); + smb_credinit(&scred, curproc, cr); + + error = smbfs_smb_tmpopen(np, rights, &scred, &fid); + if (error) + goto out; + + /* + * This does the OTW Set + */ + error = smbfs_smb_setsec_m(smi->smi_share, fid, + &scred, selector, mp); + + cerror = smbfs_smb_tmpclose(np, fid, &scred); + if (cerror) + SMBERROR("error %d closing file %s\n", + cerror, np->n_rpath); + +out: + smb_credrele(&scred); + smbfs_rw_exit(&np->r_lkserlock); + + return (error); +} + +/* + * Entry points from VOP_IOCTL + */ +int +smbfs_ioc_getsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr) +{ + ioc_sdbuf_t iocb; + mdchain_t *mdp, md_store; + mblk_t *m; + void *ubuf; + int error; + + /* + * Get the buffer information + */ + if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag)) + return (EFAULT); + + /* + * This does the OTW Get (and maybe open, close) + * Allocates and returns an mblk in &m. + */ + error = smbfs_getsd(vp, iocb.selector, &m, cr); + if (error) + return (error); + + /* + * Have m. Must free it before return. + */ + mdp = &md_store; + md_initm(mdp, m); + iocb.used = m_fixhdr(m); + + /* + * Always copyout the buffer information, + * so the user can realloc and try again + * after an EOVERFLOW return. + */ + if (ddi_copyout(&iocb, (void *)arg, sizeof (iocb), flag)) { + error = EFAULT; + goto out; + } + + if (iocb.used > iocb.alloc) { + error = EOVERFLOW; + goto out; + } + + /* + * Copyout the buffer contents (SD) + */ + ubuf = (void *)(uintptr_t)iocb.addr; + error = md_get_mem(mdp, ubuf, iocb.used, MB_MUSER); + +out: + /* Note: m_freem(m) is done by... */ + md_done(mdp); + + return (error); +} + +int +smbfs_ioc_setsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr) +{ + ioc_sdbuf_t iocb; + mbchain_t *mbp, mb_store; + void *ubuf; + int error; + + /* + * Get the buffer information + */ + if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag)) + return (EFAULT); + + if (iocb.used < sizeof (ntsecdesc_t) || + iocb.used >= MAX_RAW_SD_SIZE) + return (EINVAL); + + /* + * Get the buffer contents (security descriptor data) + */ + mbp = &mb_store; + mb_init(mbp); + ubuf = (void *)(uintptr_t)iocb.addr; + error = mb_put_mem(mbp, ubuf, iocb.used, MB_MUSER); + if (error) + goto out; + + /* + * This does the OTW Set (and maybe open, close) + * It clears mb_top when consuming the message. + */ + error = smbfs_setsd(vp, iocb.selector, &mbp->mb_top, cr); + +out: + mb_done(mbp); + return (error); + +} + +#ifdef ACL_SUPPORT +/* + * Conversion functions for VOP_GETSECATTR, VOP_SETSECATTR + * + * XXX: We may or may not add conversion code here, or we + * may add that to usr/src/common (TBD). For now all the + * ACL conversion code is in libsmbfs. + */ + +/* + * Convert a Windows SD (in the mdchain mdp) into a + * ZFS-style vsecattr_t and possibly uid, gid. + */ +/* ARGSUSED */ +static int +smb_ntsd2vsec(mdchain_t *mdp, vsecattr_t *vsa, + int *uidp, int *gidp, cred_t *cr) +{ + /* XXX NOT_YET */ + return (ENOSYS); +} + +/* + * Convert a ZFS-style vsecattr_t (and possibly uid, gid) + * into a Windows SD (built in the mbchain mbp). + */ +/* ARGSUSED */ +static int +smb_vsec2ntsd(vsecattr_t *vsa, int uid, int gid, + mbchain_t *mbp, cred_t *cr) +{ + /* XXX NOT_YET */ + return (ENOSYS); +} +#endif /* ACL_SUPPORT */ + +/* + * Entry points from VOP_GETSECATTR, VOP_SETSECATTR + * + * Disabled the real _getacl functionality for now, + * because we have no way to return the owner and + * primary group until we replace our fake uid/gid + * in getattr with something derived from _getsd. + */ + +/* ARGSUSED */ +int +smbfs_getacl(vnode_t *vp, vsecattr_t *vsa, + int *uidp, int *gidp, int flag, cred_t *cr) +{ +#ifdef ACL_SUPPORT + mdchain_t *mdp, md_store; + mblk_t *m; + uint32_t selector; + int error; + + /* + * Which parts of the SD we request. + * XXX: We need a way to let the caller specify + * what parts she wants - i.e. the SACL? + * XXX: selector |= SACL_SECURITY_INFORMATION; + * Or maybe: if we get access denied, try the + * open/fetch again without the SACL bit. + */ + selector = 0; + if (vsa) + selector |= DACL_SECURITY_INFORMATION; + if (uidp) + selector |= OWNER_SECURITY_INFORMATION; + if (gidp) + selector |= GROUP_SECURITY_INFORMATION; + if (selector == 0) + return (0); + + /* + * This does the OTW Get (and maybe open, close) + * Allocates and returns an mblk in &m. + */ + error = smbfs_getsd(vp, selector, &m, cr); + if (error) + return (error); + + /* + * Have m. Must free it before return. + */ + mdp = &md_store; + md_initm(mdp, m); + + /* + * Convert the Windows security descriptor to a + * ZFS ACL (and owner ID, primary group ID). + * This is the difficult part. (todo) + */ + error = smb_ntsd2vsec(mdp, vsa, uidp, gidp, cr); + + /* Note: m_freem(m) is done by... */ + md_done(mdp); + + return (error); +#else /* ACL_SUPPORT */ + return (ENOSYS); +#endif /* ACL_SUPPORT */ +} + + +/* ARGSUSED */ +int +smbfs_setacl(vnode_t *vp, vsecattr_t *vsa, + int uid, int gid, int flag, cred_t *cr) +{ +#ifdef ACL_SUPPORT + mbchain_t *mbp, mb_store; + uint32_t selector; + int error; + + /* + * Which parts of the SD we'll modify. + * Ditto comments above re. SACL + */ + selector = 0; + if (vsa) + selector |= DACL_SECURITY_INFORMATION; + if (uid != -1) + selector |= OWNER_SECURITY_INFORMATION; + if (gid != -1) + selector |= GROUP_SECURITY_INFORMATION; + if (selector == 0) + return (0); + + /* + * Setup buffer for SD data. + */ + mbp = &mb_store; + mb_init(mbp); + + /* + * Convert a ZFS ACL (and owner ID, group ID) + * to a Windows security descriptor. + * This is the difficult part. (todo) + */ + error = smb_vsec2ntsd(vsa, uid, gid, mbp, cr); + if (error) + goto out; + + /* + * This does the OTW Set (and maybe open, close) + * It clears mb_top when consuming the message. + */ + error = smbfs_setsd(vp, selector, &mbp->mb_top, cr); + +out: + mb_done(mbp); + return (error); +#else /* ACL_SUPPORT */ + return (ENOSYS); +#endif /* ACL_SUPPORT */ +} diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c index 789bfdfaff..2538937d2a 100644 --- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c @@ -2814,13 +2814,14 @@ again: static int smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx) { + int error = 0; if (ctx->f_name) kmem_free(ctx->f_name, ctx->f_namesz); if (ctx->f_t2) smb_t2_done(ctx->f_t2); if ((ctx->f_flags & SMBFS_RDD_NOCLOSE) == 0) - smbfs_smb_findclose2(ctx); - return (0); + error = smbfs_smb_findclose2(ctx); + return (error); } int @@ -2850,7 +2851,7 @@ smbfs_smb_findopen(struct smbnode *dnp, const char *wildcard, int wclen, error = smbfs_smb_findopenLM2(ctx, dnp, wildcard, wclen, attr, scrp); if (error) - smbfs_smb_findclose(ctx, scrp); + (void) smbfs_smb_findclose(ctx, scrp); else *ctxpp = ctx; return (error); @@ -2915,17 +2916,18 @@ smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp) int smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp) { + int error; ctx->f_scred = scrp; if (ctx->f_flags & SMBFS_RDD_USESEARCH) { - smbfs_smb_findcloseLM1(ctx); + error = smbfs_smb_findcloseLM1(ctx); } else - smbfs_smb_findcloseLM2(ctx); + error = smbfs_smb_findcloseLM2(ctx); if (ctx->f_rname) kmem_free(ctx->f_rname, ctx->f_rnamelen); if (ctx->f_firstnm) kmem_free(ctx->f_firstnm, ctx->f_firstnmlen); kmem_free(ctx, sizeof (*ctx)); - return (0); + return (error); } @@ -2991,7 +2993,7 @@ smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp, if (nmlenp) *nmlenp = ctx->f_nmlen; } - smbfs_smb_findclose(ctx, scrp); + (void) smbfs_smb_findclose(ctx, scrp); out: smbfs_rw_exit(&dnp->r_lkserlock); @@ -2999,14 +3001,15 @@ out: } /* - * Support functions for get/set security + * OTW function to Get a security descriptor (SD). + * + * Note: On success, this fills in mdp->md_top, + * which the caller should free. */ -#ifdef APPLE - int -smbfs_smb_getsec_int(struct smb_share *ssp, uint16_t fid, - struct smb_cred *scrp, uint32_t selector, - struct ntsecdesc **res, int *reslen) +smbfs_smb_getsec_m(struct smb_share *ssp, uint16_t fid, + struct smb_cred *scrp, uint32_t selector, + mblk_t **res, uint32_t *reslen) { struct smb_ntrq *ntp; struct mbchain *mbp; @@ -3017,85 +3020,194 @@ smbfs_smb_getsec_int(struct smb_share *ssp, uint16_t fid, scrp, &ntp); if (error) return (error); + + /* Parameters part */ mbp = &ntp->nt_tparam; mb_init(mbp); mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, 0); /* reserved */ mb_put_uint32le(mbp, selector); + /* Data part (none) */ + + /* Max. returned parameters and data. */ ntp->nt_maxpcount = 4; ntp->nt_maxdcount = *reslen; + error = smb_nt_request(ntp); if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) goto done; *res = NULL; + /* * if there's more data than we said we could receive, here * is where we pick up the length of it */ mdp = &ntp->nt_rparam; md_get_uint32le(mdp, reslen); + if (error) + goto done; + /* + * get the data part. + */ mdp = &ntp->nt_rdata; - if (mdp->md_top) { /* XXX md_cur safer than md_top */ - len = m_fixhdr(mdp->md_top); + if (mdp->md_top == NULL) { + SMBVDEBUG("null md_top? fid 0x%x\n", letohs(fid)); + error = EBADRPC; + goto done; + } + + /* + * The returned parameter SD_length should match + * the length of the returned data. Unfortunately, + * we have to work around server bugs here. + */ + len = m_fixhdr(mdp->md_top); + if (len != *reslen) { + SMBVDEBUG("len %d *reslen %d fid 0x%x\n", + len, *reslen, letohs(fid)); + } + + /* + * Actual data provided is < returned SD_length. + * + * The following "if (len < *reslen)" handles a Windows bug + * observed when the underlying filesystem is FAT32. In that + * case a 32 byte security descriptor comes back (S-1-1-0, ie + * "Everyone") but the Parameter Block claims 44 is the length + * of the security descriptor. (The Data Block length + * claimed is 32. This server bug was reported against NT + * first and I've personally observed it with W2K. + */ + if (len < *reslen) + *reslen = len; + + /* + * Actual data provided is > returned SD_length. + * (Seen on StorageTek NAS 5320, s/w ver. 4.21 M0) + * Narrow work-around for returned SD_length==0. + */ + if (len > *reslen) { /* - * The following "if (len < *reslen)" handles a Windows bug - * observed when the underlying filesystem is FAT32. In that - * case a 32 byte security descriptor comes back (S-1-1-0, ie - * "Everyone") but the Parameter Block claims 44 is the length - * of the security descriptor. (The Data Block length - * claimed is 32. This server bug was reported against NT - * first and I've personally observed it with W2K. + * Increase *reslen, but carefully. */ - if (len < *reslen) + if (*reslen == 0 && len <= ntp->nt_maxdcount) *reslen = len; - if (len == *reslen) { - MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK); - md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM); - } else if (len > *reslen) - SMBVDEBUG("len %d *reslen %d fid 0x%x\n", len, *reslen, - letohs(fid)); - } else - SMBVDEBUG("null md_top? fid 0x%x\n", letohs(fid)); + } + error = md_get_mbuf(mdp, len, res); + done: + if (error == 0 && *res == NULL) { + ASSERT(*res); + error = EBADRPC; + } + smb_nt_done(ntp); return (error); } +#ifdef APPLE +/* + * Wrapper for _getsd() compatible with darwin code. + */ int smbfs_smb_getsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, uint32_t selector, struct ntsecdesc **res) { - int error, olen, seclen; + int error; + uint32_t len, olen; + struct mdchain *mdp, md_store; + struct mbuf *m; + + bzero(mdp, sizeof (*mdp)); + len = 500; /* "overlarge" values => server errors */ +again: + olen = len; + error = smbfs_smb_getsec_m(ssp, fid, scrp, selector, &m, &len); + /* + * Server may give us an error indicating that we + * need a larger data buffer to receive the SD, + * and the size we'll need. Use the given size, + * but only after a sanity check. + * + * XXX: Check for specific error values here? + * XXX: also ... && len <= MAX_RAW_SD_SIZE + */ + if (error && len > olen) + goto again; + + if (error) + return (error); + + mdp = &md_store; + md_initm(mdp, m); + MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK); + error = md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM); + md_done(mdp); - olen = seclen = 500; /* "overlarge" values => server errors */ - error = smbfs_smb_getsec_int(ssp, fid, scrp, selector, res, &seclen); - if (error && seclen > olen) - error = smbfs_smb_getsec_int(ssp, fid, scrp, selector, res, - &seclen); return (error); } +#endif /* APPLE */ -int -smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, - uint32_t selector, uint16_t flags, struct ntsid *owner, - struct ntsid *group, struct ntacl *sacl, struct ntacl *dacl) +/* + * OTW function to Set a security descriptor (SD). + * Caller data are carried in an mbchain_t. + * + * Note: This normally consumes mbp->mb_top, and clears + * that pointer when it does. + */ +int smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid, + struct smb_cred *scrp, uint32_t selector, mblk_t **mp) { struct smb_ntrq *ntp; struct mbchain *mbp; - int error, off; - struct ntsecdesc ntsd; + int error; error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC, scrp, &ntp); if (error) return (error); + + /* Parameters part */ mbp = &ntp->nt_tparam; mb_init(mbp); mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, 0); /* reserved */ mb_put_uint32le(mbp, selector); + + /* Data part */ mbp = &ntp->nt_tdata; + mb_initm(mbp, *mp); + *mp = NULL; /* consumed */ + + /* No returned parameters or data. */ + ntp->nt_maxpcount = 0; + ntp->nt_maxdcount = 0; + + error = smb_nt_request(ntp); + smb_nt_done(ntp); + + return (error); +} + +#ifdef APPLE +/* + * This function builds the SD given the various parts. + */ +int +smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, + uint32_t selector, uint16_t flags, struct ntsid *owner, + struct ntsid *group, struct ntacl *sacl, struct ntacl *dacl) +{ + struct mbchain *mbp, mb_store; + struct ntsecdesc ntsd; + int error, off; + + /* + * Build the SD as its own mbuf chain and pass it to + * smbfs_smb_setsec_m() + */ + mbp = &mb_store; mb_init(mbp); bzero(&ntsd, sizeof (ntsd)); wset_sdrevision(&ntsd); @@ -3137,10 +3249,14 @@ smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, mb_put_mem(mbp, (caddr_t)sacl, acllen(sacl), MB_MSYSTEM); if (dacl) mb_put_mem(mbp, (caddr_t)dacl, acllen(dacl), MB_MSYSTEM); - ntp->nt_maxpcount = 0; - ntp->nt_maxdcount = 0; - error = smb_nt_request(ntp); - smb_nt_done(ntp); + + /* + * Just pass the mbuf to _setsec_m + * It will clear mb_top if consumed. + */ + error = smbfs_smb_setsec_m(ssp, fid, scrp, selector, &mbp->mb_top); + mb_done(mbp); + return (error); } diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h index 18641420f0..feb186ac76 100644 --- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h @@ -42,8 +42,8 @@ #pragma ident "%Z%%M% %I% %E% SMI" -/* This defines terms used in the error messages */ #include <sys/cmn_err.h> +#include <netsmb/mchain.h> #if defined(DEBUG) || defined(lint) #define SMB_VNODE_DEBUG 1 @@ -73,7 +73,6 @@ #define SMB_LOCK_SHARED 1 #define SMB_LOCK_RELEASE 2 -struct mbchain; struct smb_cred; struct smb_vc; struct statvfs; @@ -206,6 +205,23 @@ int smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp); int smbfs_0extend(vnode_t *vp, uint16_t fid, len_t from, len_t to, struct smb_cred *scredp, int timo); +/* get/set security descriptor */ +int smbfs_smb_getsec_m(struct smb_share *ssp, uint16_t fid, + struct smb_cred *scrp, uint32_t selector, + mblk_t **res, uint32_t *reslen); +int smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid, + struct smb_cred *scrp, uint32_t selector, mblk_t **mp); + +int smbfs_getacl(vnode_t *vp, vsecattr_t *vsecattr, + int *uidp, int *gidp, int flag, cred_t *cr); +int smbfs_setacl(vnode_t *vp, vsecattr_t *vsecattr, + int uid, int gid, int flag, cred_t *cr); + +int smbfs_getsd(vnode_t *vp, uint32_t sel, mblk_t **mp, cred_t *cr); +int smbfs_setsd(vnode_t *vp, uint32_t sel, mblk_t **mp, cred_t *cr); +int smbfs_ioc_getsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr); +int smbfs_ioc_setsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr); + #ifdef NOT_YET int smbfs_smb_getsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, uint32_t selector, struct ntsecdesc **res); diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c index 63754da4f4..02cbe68382 100644 --- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c @@ -43,6 +43,7 @@ #include <sys/cred.h> #include <sys/vnode.h> #include <sys/vfs.h> +#include <sys/filio.h> #include <sys/uio.h> #include <sys/dirent.h> #include <sys/errno.h> @@ -62,6 +63,7 @@ #include <smbfs/smbfs_node.h> #include <smbfs/smbfs_subr.h> +#include <sys/fs/smbfs_ioctl.h> #include <fs/fs_subr.h> /* @@ -116,6 +118,8 @@ static int smbfs_read(vnode_t *, struct uio *, int, cred_t *, caller_context_t *); static int smbfs_write(vnode_t *, struct uio *, int, cred_t *, caller_context_t *); +static int smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *, + caller_context_t *); static int smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *, caller_context_t *); static int smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *, @@ -148,6 +152,10 @@ static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t, cred_t *, caller_context_t *); static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *, caller_context_t *); +static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *, + caller_context_t *); +static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *, + caller_context_t *); static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *, caller_context_t *); @@ -161,48 +169,47 @@ struct vnodeops *smbfs_vnodeops = NULL; /* * Most unimplemented ops will return ENOSYS because of fs_nosys(). * The only ops where that won't work are ACCESS (due to open(2) - * failures) and GETSECATTR (due to acl(2) failures). + * failures) and ... (anything else left?) */ const fs_operation_def_t smbfs_vnodeops_template[] = { - { VOPNAME_OPEN, { .vop_open = smbfs_open } }, - { VOPNAME_CLOSE, { .vop_close = smbfs_close } }, - { VOPNAME_READ, { .vop_read = smbfs_read } }, - { VOPNAME_WRITE, { .vop_write = smbfs_write } }, - { VOPNAME_IOCTL, { .error = fs_nosys } }, /* smbfs_ioctl, */ - { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } }, - { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } }, - { VOPNAME_ACCESS, { .vop_access = smbfs_access } }, - { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } }, - { VOPNAME_CREATE, { .vop_create = smbfs_create } }, - { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } }, - { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */ - { VOPNAME_RENAME, { .vop_rename = smbfs_rename } }, - { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } }, - { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } }, - { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } }, - { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */ - { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */ - { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } }, - { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } }, - { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */ - { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } }, - { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } }, - { VOPNAME_SEEK, { .vop_seek = smbfs_seek } }, - { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } }, - { VOPNAME_SPACE, { .vop_space = smbfs_space } }, - { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */ - { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */ - { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */ - { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */ - { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */ - { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */ - { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */ - { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } }, - { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */ - { VOPNAME_SETSECATTR, { .error = fs_nosys } }, /* smbfs_setsecattr, */ - { VOPNAME_GETSECATTR, { .error = noop_vnodeop } }, - /* smbfs_getsecattr, */ - { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } }, + { VOPNAME_OPEN, { .vop_open = smbfs_open } }, + { VOPNAME_CLOSE, { .vop_close = smbfs_close } }, + { VOPNAME_READ, { .vop_read = smbfs_read } }, + { VOPNAME_WRITE, { .vop_write = smbfs_write } }, + { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } }, + { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } }, + { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } }, + { VOPNAME_ACCESS, { .vop_access = smbfs_access } }, + { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } }, + { VOPNAME_CREATE, { .vop_create = smbfs_create } }, + { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } }, + { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */ + { VOPNAME_RENAME, { .vop_rename = smbfs_rename } }, + { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } }, + { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } }, + { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } }, + { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */ + { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */ + { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } }, + { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } }, + { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */ + { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } }, + { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } }, + { VOPNAME_SEEK, { .vop_seek = smbfs_seek } }, + { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } }, + { VOPNAME_SPACE, { .vop_space = smbfs_space } }, + { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */ + { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */ + { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */ + { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */ + { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */ + { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */ + { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */ + { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } }, + { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */ + { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } }, + { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } }, + { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } }, { NULL, NULL } }; @@ -594,6 +601,64 @@ smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, } +/* ARGSUSED */ +static int +smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, + cred_t *cr, int *rvalp, caller_context_t *ct) +{ + int error; + smbmntinfo_t *smi; + + smi = VTOSMI(vp); + + if (curproc->p_zone != smi->smi_zone) + return (EIO); + + if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) + return (EIO); + + switch (cmd) { + /* First three from ZFS. XXX - need these? */ + + case _FIOFFS: + error = smbfs_fsync(vp, 0, cr, ct); + break; + + /* + * The following two ioctls are used by bfu. + * Silently ignore to avoid bfu errors. + */ + case _FIOGDIO: + case _FIOSDIO: + error = 0; + break; + +#ifdef NOT_YET /* XXX - from the NFS code. */ + case _FIODIRECTIO: + error = smbfs_directio(vp, (int)arg, cr); +#endif + + /* + * Allow get/set with "raw" security descriptor (SD) data. + * Useful for testing, diagnosing idmap problems, etc. + */ + case SMBFSIO_GETSD: + error = smbfs_ioc_getsd(vp, arg, flag, cr); + break; + + case SMBFSIO_SETSD: + error = smbfs_ioc_setsd(vp, arg, flag, cr); + break; + + default: + error = ENOTTY; + break; + } + + return (error); +} + + /* * Return either cached or remote attributes. If get remote attr * use them to check and invalidate caches, then cache the new attributes. @@ -2466,8 +2531,16 @@ smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, *valp = 1; break; + case _PC_ACL_ENABLED: + /* + * Always say "yes" here. Our _getsecattr + * will build a trivial ACL when needed, + * i.e. when server does not have ACLs. + */ + *valp = _ACL_ACE_ENABLED; + break; + case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */ - case _PC_ACL_ENABLED: /* No ACLs yet - see FILE_PERSISTENT_ACLS bit */ case _PC_XATTR_EXISTS: /* No xattrs yet */ *valp = 0; break; @@ -2478,6 +2551,96 @@ smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, return (0); } +/* ARGSUSED */ +static int +smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, + caller_context_t *ct) +{ + vfs_t *vfsp; + smbmntinfo_t *smi; + int error, uid, gid; + uint_t mask; + + vfsp = vp->v_vfsp; + smi = VFTOSMI(vfsp); + + if (curproc->p_zone != smi->smi_zone) + return (EIO); + + if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) + return (EIO); + + /* + * Our _pathconf indicates _ACL_ACE_ENABLED, + * so we should only see VSA_ACE, etc here. + * Note: vn_create asks for VSA_DFACLCNT, + * and it expects ENOSYS and empty data. + */ + mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT | + VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); + if (mask == 0) + return (ENOSYS); + + /* XXX - access check ACE_READ_ACL? */ + + if (smi->smi_fsattr & FILE_PERSISTENT_ACLS) { + error = smbfs_getacl(vp, vsa, &uid, &gid, flag, cr); + /* XXX: Save uid/gid somewhere? */ + } else + error = ENOSYS; + + if (error == ENOSYS) + error = fs_fab_acl(vp, vsa, flag, cr, ct); + + return (error); +} + +/* ARGSUSED */ +static int +smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, + caller_context_t *ct) +{ + vfs_t *vfsp; + smbmntinfo_t *smi; + int error; + uint_t mask; + + vfsp = vp->v_vfsp; + smi = VFTOSMI(vfsp); + + if (curproc->p_zone != smi->smi_zone) + return (EIO); + + if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) + return (EIO); + + /* + * Our _pathconf indicates _ACL_ACE_ENABLED, + * so we should only see VSA_ACE, etc here. + */ + mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT); + if (mask == 0) + return (ENOSYS); + + /* + * If and when smbfs_access is extended, we can + * check ACE_WRITE_ACL here instead. (XXX todo) + * For now, in-line parts of smbfs_access, + * i.e. only allow _setacl by the owner, + * and check for read-only FS. + */ + if (vfsp->vfs_flag & VFS_RDONLY) + return (EROFS); + if (crgetuid(cr) != smi->smi_args.uid) + return (EACCES); + + if (smi->smi_fsattr & FILE_PERSISTENT_ACLS) { + error = smbfs_setacl(vp, vsa, -1, -1, flag, cr); + } else + error = ENOSYS; + + return (error); +} /* diff --git a/usr/src/uts/common/netsmb/mchain.h b/usr/src/uts/common/netsmb/mchain.h index e6fb362a9c..7009ba75bf 100644 --- a/usr/src/uts/common/netsmb/mchain.h +++ b/usr/src/uts/common/netsmb/mchain.h @@ -160,7 +160,7 @@ int mb_put_uint64be(struct mbchain *mbp, uint64_t x); int mb_put_uint64le(struct mbchain *mbp, uint64_t x); int mb_put_mem(struct mbchain *mbp, const char *src, int size, int type); -int mb_put_mblk(struct mbchain *mbp, mblk_t *m); +int mb_put_mbuf(struct mbchain *mbp, mblk_t *m); int mb_put_uio(struct mbchain *mbp, uio_t *uiop, int size); int md_init(struct mdchain *mdp); @@ -179,7 +179,7 @@ int md_get_uint64(struct mdchain *mdp, uint64_t *x); int md_get_uint64be(struct mdchain *mdp, uint64_t *x); int md_get_uint64le(struct mdchain *mdp, uint64_t *x); int md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type); -int md_get_mblk(struct mdchain *mdp, int size, mblk_t **m); +int md_get_mbuf(struct mdchain *mdp, int size, mblk_t **m); int md_get_uio(struct mdchain *mdp, uio_t *uiop, int size); /* diff --git a/usr/src/uts/common/sys/fs/smbfs_ioctl.h b/usr/src/uts/common/sys/fs/smbfs_ioctl.h new file mode 100644 index 0000000000..8f90e40274 --- /dev/null +++ b/usr/src/uts/common/sys/fs/smbfs_ioctl.h @@ -0,0 +1,64 @@ +/* + * 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_IOCTL_H +#define _SMBFS_IOCTL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Project private IOCTL interface provided by SMBFS. + */ + +#include <sys/ioccom.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ioc_sdbuf { + uint64_t addr; /* buffer address (user space) */ + uint32_t alloc; /* allocated length */ + uint32_t used; /* content length */ + uint32_t selector; /* i.e. DACL_SECURITY_INFORMATION */ +} ioc_sdbuf_t; + +/* + * SMBFS ioctl codes + * + * We only need a couple of these, so (re)using some + * FS-specific ioctl codes from sys/filio.h + * Data for both is ioc_sdbuf_t + */ + +#define SMBFSIO_GETSD _IO('f', 81) +#define SMBFSIO_SETSD _IO('f', 82) + +#ifdef __cplusplus +} +#endif + +#endif /* _SMBFS_IOCTL_H */ |