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 2008 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_lib.h> 53 #include <netsmb/smbfs_acl.h> 54 #include <netsmb/smbfs_isec.h> 55 #include "private.h" 56 57 /* Sanity check SD sizes */ 58 #define MAX_RAW_SD_SIZE 32768 59 60 /* XXX: acl_common.h */ 61 acl_t *acl_alloc(enum acl_type); 62 void acl_free(acl_t *); 63 64 65 /* 66 * Get/set a Windows security descriptor (SD) 67 * using the (private) smbfs ioctl mechanism. 68 * Note: Get allocates mbp->mb_top 69 */ 70 71 /* ARGSUSED */ 72 int 73 smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) 74 { 75 ioc_sdbuf_t iocb; 76 struct mbuf *m; 77 int error; 78 79 error = mb_init(mbp, MAX_RAW_SD_SIZE); 80 if (error) 81 return (error); 82 83 m = mbp->mb_top; 84 iocb.addr = mtod(m, uintptr_t); 85 iocb.alloc = m->m_maxlen; 86 iocb.used = 0; 87 iocb.selector = selector; 88 89 /* 90 * This does the OTW Get. 91 */ 92 if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { 93 error = errno; 94 goto errout; 95 } 96 97 m->m_len = iocb.used; 98 return (0); 99 100 errout: 101 mb_done(mbp); 102 return (error); 103 } 104 105 /* ARGSUSED */ 106 int 107 smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) 108 { 109 ioc_sdbuf_t iocb; 110 struct mbuf *m; 111 int error; 112 113 /* Make the data contiguous. */ 114 error = m_lineup(mbp->mb_top, &m); 115 if (error) 116 return (error); 117 118 if (mbp->mb_top != m) 119 mb_initm(mbp, m); 120 121 iocb.addr = mtod(m, uintptr_t); 122 iocb.alloc = m->m_maxlen; 123 iocb.used = m->m_len; 124 iocb.selector = selector; 125 126 /* 127 * This does the OTW Set. 128 */ 129 if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) 130 error = errno; 131 132 return (error); 133 } 134 135 /* 136 * Get an NT SD from the open file via ioctl. 137 */ 138 int 139 smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp) 140 { 141 mbdata_t *mbp, mb_store; 142 int error; 143 144 mbp = &mb_store; 145 bzero(mbp, sizeof (*mbp)); 146 147 /* 148 * Get the raw Windows SD via ioctl. 149 * Returns allocated mbchain in mbp. 150 */ 151 error = smbfs_acl_iocget(fd, selector, mbp); 152 if (error == 0) { 153 /* 154 * Import the raw SD into "internal" form. 155 * (like "absolute" form per. NT docs) 156 * Returns allocated data in sdp 157 */ 158 error = mb_get_ntsd(mbp, sdp); 159 } 160 161 mb_done(mbp); 162 return (error); 163 } 164 165 /* 166 * Set an NT SD onto the open file via ioctl. 167 */ 168 int 169 smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd) 170 { 171 mbdata_t *mbp, mb_store; 172 int error; 173 174 mbp = &mb_store; 175 mb_init(mbp, M_MINSIZE); 176 177 /* 178 * Export the "internal" SD into an mb chain. 179 * (a.k.a "self-relative" form per. NT docs) 180 * Returns allocated mbchain in mbp. 181 */ 182 error = mb_put_ntsd(mbp, sd); 183 if (error == 0) { 184 /* 185 * Set the raw Windows SD via ioctl. 186 */ 187 error = smbfs_acl_iocset(fd, selector, mbp); 188 } 189 190 mb_done(mbp); 191 192 return (error); 193 } 194 195 196 197 /* 198 * Convenience function to Get security using a 199 * ZFS-style ACL (libsec acl, type=ACE_T) 200 * Intentionally similar to: facl_get(3SEC) 201 */ 202 int 203 smbfs_acl_get(int fd, acl_t **aclp, uid_t *uidp, gid_t *gidp) 204 { 205 i_ntsd_t *sd = NULL; 206 acl_t *acl = NULL; 207 uint32_t selector; 208 int error; 209 210 /* 211 * Which parts of the SD are being requested? 212 * XXX: Should we request the SACL too? If so, 213 * might that cause this access to be denied? 214 * Or maybe: if we get access denied, try the 215 * open/fetch again without the SACL bit. 216 */ 217 selector = 0; 218 if (aclp) 219 selector |= DACL_SECURITY_INFORMATION; 220 if (uidp) 221 selector |= OWNER_SECURITY_INFORMATION; 222 if (gidp) 223 selector |= GROUP_SECURITY_INFORMATION; 224 225 if (selector == 0) 226 return (0); 227 228 /* 229 * Get the Windows SD via ioctl, in 230 * "internal" (absolute) form. 231 */ 232 error = smbfs_acl_getsd(fd, selector, &sd); 233 if (error) 234 return (error); 235 /* Note: sd now holds allocated data. */ 236 237 /* 238 * Convert the internal SD to a ZFS ACL. 239 * Get uid/gid too if pointers != NULL. 240 */ 241 if (aclp) { 242 acl = acl_alloc(ACE_T); 243 if (acl == NULL) { 244 error = ENOMEM; 245 goto out; 246 } 247 } 248 error = smbfs_acl_sd2zfs(sd, acl, uidp, gidp); 249 if (error) 250 goto out; 251 252 /* Success! */ 253 if (aclp) { 254 *aclp = acl; 255 acl = NULL; 256 } 257 258 out: 259 if (acl) 260 acl_free(acl); 261 smbfs_acl_free_sd(sd); 262 return (error); 263 } 264 265 /* 266 * Convenience function to Set security using a 267 * ZFS-style ACL (libsec acl, type=ACE_T) 268 * Intentionally similar to: facl_set(3SEC) 269 */ 270 int 271 smbfs_acl_set(int fd, acl_t *acl, uid_t uid, gid_t gid) 272 { 273 i_ntsd_t *sd = NULL; 274 uint32_t selector; 275 int error; 276 277 /* 278 * Which parts of the SD are being modified? 279 * XXX: Ditto comments above re. SACL. 280 */ 281 selector = 0; 282 if (acl) 283 selector |= DACL_SECURITY_INFORMATION; 284 if (uid != (uid_t)-1) 285 selector |= OWNER_SECURITY_INFORMATION; 286 if (gid != (gid_t)-1) 287 selector |= GROUP_SECURITY_INFORMATION; 288 if (selector == 0) 289 return (0); 290 291 if (acl && acl->acl_type != ACE_T) 292 return (EINVAL); 293 294 /* 295 * Convert the ZFS ACL to an internal SD. 296 * Returns allocated data in sd 297 */ 298 error = smbfs_acl_zfs2sd(acl, uid, gid, &sd); 299 if (error == 0) 300 error = smbfs_acl_setsd(fd, selector, sd); 301 302 smbfs_acl_free_sd(sd); 303 304 return (error); 305 } 306