Home | History | Annotate | Download | only in smb
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * ACL API for smbfs
     29  */
     30 
     31 #include <sys/types.h>
     32 #include <sys/errno.h>
     33 #include <sys/cred.h>
     34 #include <sys/cmn_err.h>
     35 #include <sys/kmem.h>
     36 #include <sys/sunddi.h>
     37 #include <sys/acl.h>
     38 #include <sys/vnode.h>
     39 #include <sys/vfs.h>
     40 #include <sys/byteorder.h>
     41 
     42 #include <errno.h>
     43 #include <stdio.h>
     44 #include <strings.h>
     45 #include <unistd.h>
     46 
     47 #include <umem.h>
     48 #include <idmap.h>
     49 
     50 #include <sys/fs/smbfs_ioctl.h>
     51 
     52 #include <netsmb/smb.h>
     53 #include <netsmb/smb_lib.h>
     54 #include <netsmb/smbfs_acl.h>
     55 
     56 #include "smbfs_ntacl.h"
     57 #include "private.h"
     58 
     59 /* Sanity check SD sizes */
     60 #define	MAX_RAW_SD_SIZE	32768
     61 
     62 /* XXX: acl_common.h */
     63 acl_t *acl_alloc(enum acl_type);
     64 void acl_free(acl_t *);
     65 
     66 
     67 /*
     68  * Get/set a Windows security descriptor (SD)
     69  * using the (private) smbfs ioctl mechanism.
     70  * Note: Get allocates mbp->mb_top
     71  */
     72 
     73 /* ARGSUSED */
     74 int
     75 smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp)
     76 {
     77 	ioc_sdbuf_t	iocb;
     78 	struct mbuf	*m;
     79 	int		error;
     80 
     81 	error = mb_init_sz(mbp, MAX_RAW_SD_SIZE);
     82 	if (error)
     83 		return (error);
     84 
     85 	m = mbp->mb_top;
     86 	iocb.addr = mtod(m, uintptr_t);
     87 	iocb.alloc = m->m_maxlen;
     88 	iocb.used = 0;
     89 	iocb.selector = selector;
     90 
     91 	/*
     92 	 * This does the OTW Get.
     93 	 */
     94 	if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) {
     95 		error = errno;
     96 		goto errout;
     97 	}
     98 
     99 	m->m_len = iocb.used;
    100 	return (0);
    101 
    102 errout:
    103 	mb_done(mbp);
    104 	return (error);
    105 }
    106 
    107 /* ARGSUSED */
    108 int
    109 smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp)
    110 {
    111 	ioc_sdbuf_t	iocb;
    112 	struct mbuf	*m;
    113 	int		error;
    114 
    115 	/* Make the data contiguous. */
    116 	error = m_lineup(mbp->mb_top, &m);
    117 	if (error)
    118 		return (error);
    119 
    120 	if (mbp->mb_top != m)
    121 		mb_initm(mbp, m);
    122 
    123 	iocb.addr = mtod(m, uintptr_t);
    124 	iocb.alloc = m->m_maxlen;
    125 	iocb.used  = m->m_len;
    126 	iocb.selector = selector;
    127 
    128 	/*
    129 	 * This does the OTW Set.
    130 	 */
    131 	if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0)
    132 		error = errno;
    133 
    134 	return (error);
    135 }
    136 
    137 /*
    138  * Get an NT SD from the open file via ioctl.
    139  */
    140 int
    141 smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp)
    142 {
    143 	mbdata_t *mbp, mb_store;
    144 	int error;
    145 
    146 	mbp = &mb_store;
    147 	bzero(mbp, sizeof (*mbp));
    148 
    149 	/*
    150 	 * Get the raw Windows SD via ioctl.
    151 	 * Returns allocated mbchain in mbp.
    152 	 */
    153 	error = smbfs_acl_iocget(fd, selector, mbp);
    154 	if (error == 0) {
    155 		/*
    156 		 * Import the raw SD into "internal" form.
    157 		 * (like "absolute" form per. NT docs)
    158 		 * Returns allocated data in sdp
    159 		 */
    160 		error = md_get_ntsd(mbp, sdp);
    161 	}
    162 
    163 	mb_done(mbp);
    164 	return (error);
    165 }
    166 
    167 /*
    168  * Set an NT SD onto the open file via ioctl.
    169  */
    170 int
    171 smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd)
    172 {
    173 	mbdata_t *mbp, mb_store;
    174 	int error;
    175 
    176 	mbp = &mb_store;
    177 	error = mb_init_sz(mbp, MAX_RAW_SD_SIZE);
    178 	if (error)
    179 		return (error);
    180 
    181 	/*
    182 	 * Export the "internal" SD into an mb chain.
    183 	 * (a.k.a "self-relative" form per. NT docs)
    184 	 * Returns allocated mbchain in mbp.
    185 	 */
    186 	error = mb_put_ntsd(mbp, sd);
    187 	if (error == 0) {
    188 		/*
    189 		 * Set the raw Windows SD via ioctl.
    190 		 */
    191 		error = smbfs_acl_iocset(fd, selector, mbp);
    192 	}
    193 
    194 	mb_done(mbp);
    195 
    196 	return (error);
    197 }
    198 
    199 
    200 
    201 /*
    202  * Convenience function to Get security using a
    203  * ZFS-style ACL (libsec acl, type=ACE_T)
    204  * Intentionally similar to: facl_get(3SEC)
    205  */
    206 int
    207 smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp)
    208 {
    209 	i_ntsd_t *sd = NULL;
    210 	acl_t *acl = NULL;
    211 	uint32_t selector;
    212 	int error;
    213 
    214 	/*
    215 	 * Which parts of the SD are being requested?
    216 	 * XXX: Should we request the SACL too?  If so,
    217 	 * might that cause this access to be denied?
    218 	 * Or maybe: if we get access denied, try the
    219 	 * open/fetch again without the SACL bit.
    220 	 */
    221 	selector = 0;
    222 	if (aclp)
    223 		selector |= DACL_SECURITY_INFORMATION;
    224 	if (uidp)
    225 		selector |= OWNER_SECURITY_INFORMATION;
    226 	if (gidp)
    227 		selector |= GROUP_SECURITY_INFORMATION;
    228 
    229 	if (selector == 0)
    230 		return (0);
    231 
    232 	/*
    233 	 * Get the Windows SD via ioctl, in
    234 	 * "internal" (absolute) form.
    235 	 */
    236 	error = smbfs_acl_getsd(fd, selector, &sd);
    237 	if (error)
    238 		return (error);
    239 	/* Note: sd now holds allocated data. */
    240 
    241 	/*
    242 	 * Convert the internal SD to a ZFS ACL.
    243 	 * Get uid/gid too if pointers != NULL.
    244 	 */
    245 	if (aclp) {
    246 		acl = acl_alloc(ACE_T);
    247 		if (acl == NULL) {
    248 			error = ENOMEM;
    249 			goto out;
    250 		}
    251 	}
    252 	error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp);
    253 	if (error)
    254 		goto out;
    255 
    256 	/* Success! */
    257 	if (aclp) {
    258 		*aclp = acl;
    259 		acl = NULL;
    260 	}
    261 
    262 out:
    263 	if (acl)
    264 		acl_free(acl);
    265 	smbfs_acl_free_sd(sd);
    266 	return (error);
    267 }
    268 
    269 /*
    270  * Convenience function to Set security using a
    271  * ZFS-style ACL (libsec acl, type=ACE_T)
    272  * Intentionally similar to: facl_set(3SEC)
    273  */
    274 int
    275 smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid)
    276 {
    277 	struct stat st;
    278 	i_ntsd_t *sd = NULL;
    279 	uint32_t selector;
    280 	int error;
    281 
    282 	if (acl && acl->acl_type != ACE_T)
    283 		return (EINVAL);
    284 
    285 	/*
    286 	 * Which parts of the SD are being modified?
    287 	 * XXX: Ditto comments above re. SACL.
    288 	 */
    289 	selector = 0;
    290 	if (acl)
    291 		selector |= DACL_SECURITY_INFORMATION;
    292 	if (uid != (uid_t)-1)
    293 		selector |= OWNER_SECURITY_INFORMATION;
    294 	if (gid != (gid_t)-1)
    295 		selector |= GROUP_SECURITY_INFORMATION;
    296 	if (selector == 0)
    297 		return (0);
    298 
    299 	if (uid == (uid_t)-1 || gid == (gid_t)-1) {
    300 		/*
    301 		 * If not setting owner or group, we need the
    302 		 * current owner and group for translating
    303 		 * references via owner@ or group@ ACEs.
    304 		 */
    305 		if (fstat(fd, &st) != 0)
    306 			return (errno);
    307 		if (uid == (uid_t)-1)
    308 			uid = st.st_uid;
    309 		if (gid == (gid_t)-1)
    310 			gid = st.st_gid;
    311 	}
    312 
    313 	/*
    314 	 * Convert the ZFS ACL to an internal SD.
    315 	 * Returns allocated data in sd
    316 	 */
    317 	error = smbfs_acl_zfs2sd(acl, uid, gid, selector, &sd);
    318 	if (error == 0)
    319 		error = smbfs_acl_setsd(fd, selector, sd);
    320 
    321 	smbfs_acl_free_sd(sd);
    322 
    323 	return (error);
    324 }
    325