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