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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * ACL support for smbfs 29 */ 30 31 #include <sys/systm.h> /* bcopy, ... */ 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 <netsmb/mchain.h> 43 #include <netsmb/smb.h> 44 #include <netsmb/smb_conn.h> 45 #include <netsmb/smb_osdep.h> 46 #include <netsmb/smb_subr.h> 47 48 #include <smbfs/smbfs.h> 49 #include <smbfs/smbfs_node.h> 50 #include <smbfs/smbfs_subr.h> 51 52 #include <sys/fs/smbfs_ioctl.h> 53 #include <fs/fs_subr.h> 54 #include "smbfs_ntacl.h" 55 56 /* Sanity check SD sizes */ 57 #define MAX_RAW_SD_SIZE 32768 58 #define SMALL_SD_SIZE 1024 59 60 /* 61 * smbfs_getsd() is a common function used by both 62 * smbfs_ioctl SMBFSIO_GETSD and VOP_GETSECATTR. 63 * Handles required rights, tmpopen/tmpclose. 64 * 65 * Note: smbfs_getsd allocates and returns an mblk chain, 66 * which the caller must free. 67 */ 68 int 69 smbfs_getsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr) 70 { 71 struct smb_cred scred; 72 int error, cerror; 73 smbmntinfo_t *smi; 74 smbnode_t *np; 75 u_int16_t fid = SMB_FID_UNUSED; 76 uint32_t sdlen = SMALL_SD_SIZE; 77 uint32_t rights = STD_RIGHT_READ_CONTROL_ACCESS; 78 79 if (selector & SACL_SECURITY_INFORMATION) 80 rights |= SEC_RIGHT_SYSTEM_SECURITY; 81 82 np = VTOSMB(vp); 83 smi = VTOSMI(vp); 84 85 /* Shared lock for (possible) n_fid use. */ 86 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 87 return (EINTR); 88 smb_credinit(&scred, cr); 89 90 error = smbfs_smb_tmpopen(np, rights, &scred, &fid); 91 if (error) 92 goto out; 93 94 again: 95 /* 96 * This does the OTW Get 97 */ 98 error = smbfs_smb_getsec_m(smi->smi_share, fid, 99 &scred, selector, mp, &sdlen); 100 /* 101 * Server may give us an error indicating that we 102 * need a larger data buffer to receive the SD, 103 * and the size we'll need. Use the given size, 104 * but only after a sanity check. 105 * 106 * Let's check for specific error values here. 107 * The NT error is: STATUS_BUFFER_TOO_SMALL, 108 * or with old error codes, one of these: 109 * ERRSRV/ERRnoroom, ERRDOS/122, ERRDOS/111 110 * Those are mapped to: EMOREDATA, which is 111 * later converted to E2BIG. 112 */ 113 if (error == E2BIG && 114 sdlen > SMALL_SD_SIZE && 115 sdlen <= MAX_RAW_SD_SIZE) 116 goto again; 117 118 cerror = smbfs_smb_tmpclose(np, fid, &scred); 119 if (cerror) 120 SMBVDEBUG("error %d closing file %s\n", 121 cerror, np->n_rpath); 122 123 out: 124 smb_credrele(&scred); 125 smbfs_rw_exit(&np->r_lkserlock); 126 127 return (error); 128 } 129 130 int 131 smbfs_setsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr) 132 { 133 struct smb_cred scred; 134 int error, cerror; 135 smbmntinfo_t *smi; 136 smbnode_t *np; 137 uint32_t rights; 138 u_int16_t fid = SMB_FID_UNUSED; 139 140 np = VTOSMB(vp); 141 smi = VTOSMI(vp); 142 143 /* 144 * Which parts of the SD are we setting? 145 * What rights do we need for that? 146 */ 147 if (selector == 0) 148 return (0); 149 rights = 0; 150 if (selector & (OWNER_SECURITY_INFORMATION | 151 GROUP_SECURITY_INFORMATION)) 152 rights |= STD_RIGHT_WRITE_OWNER_ACCESS; 153 if (selector & DACL_SECURITY_INFORMATION) 154 rights |= STD_RIGHT_WRITE_DAC_ACCESS; 155 if (selector & SACL_SECURITY_INFORMATION) 156 rights |= SEC_RIGHT_SYSTEM_SECURITY; 157 158 /* Shared lock for (possible) n_fid use. */ 159 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 160 return (EINTR); 161 smb_credinit(&scred, cr); 162 163 error = smbfs_smb_tmpopen(np, rights, &scred, &fid); 164 if (error) 165 goto out; 166 167 /* 168 * This does the OTW Set 169 */ 170 error = smbfs_smb_setsec_m(smi->smi_share, fid, 171 &scred, selector, mp); 172 173 cerror = smbfs_smb_tmpclose(np, fid, &scred); 174 if (cerror) 175 SMBVDEBUG("error %d closing file %s\n", 176 cerror, np->n_rpath); 177 178 out: 179 smb_credrele(&scred); 180 smbfs_rw_exit(&np->r_lkserlock); 181 182 return (error); 183 } 184 185 /* 186 * Helper for VOP_IOCTL: SMBFSIO_GETSD 187 */ 188 int 189 smbfs_ioc_getsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr) 190 { 191 ioc_sdbuf_t iocb; 192 mdchain_t *mdp, md_store; 193 mblk_t *m; 194 void *ubuf; 195 int error; 196 197 /* 198 * Get the buffer information 199 */ 200 if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag)) 201 return (EFAULT); 202 203 /* 204 * This does the OTW Get (and maybe open, close) 205 * Allocates and returns an mblk in &m. 206 */ 207 error = smbfs_getsd(vp, iocb.selector, &m, cr); 208 if (error) 209 return (error); 210 211 /* 212 * Have m. Must free it before return. 213 */ 214 mdp = &md_store; 215 md_initm(mdp, m); 216 iocb.used = m_fixhdr(m); 217 218 /* 219 * Always copyout the buffer information, 220 * so the user can realloc and try again 221 * after an EOVERFLOW return. 222 */ 223 if (ddi_copyout(&iocb, (void *)arg, sizeof (iocb), flag)) { 224 error = EFAULT; 225 goto out; 226 } 227 228 if (iocb.used > iocb.alloc) { 229 error = EOVERFLOW; 230 goto out; 231 } 232 233 /* 234 * Copyout the buffer contents (SD) 235 */ 236 ubuf = (void *)(uintptr_t)iocb.addr; 237 error = md_get_mem(mdp, ubuf, iocb.used, MB_MUSER); 238 239 out: 240 /* Note: m_freem(m) is done by... */ 241 md_done(mdp); 242 243 return (error); 244 } 245 246 /* 247 * Helper for VOP_IOCTL: SMBFSIO_SETSD 248 */ 249 int 250 smbfs_ioc_setsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr) 251 { 252 ioc_sdbuf_t iocb; 253 mbchain_t *mbp, mb_store; 254 void *ubuf; 255 int error; 256 257 /* 258 * Get the buffer information 259 */ 260 if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag)) 261 return (EFAULT); 262 263 if (iocb.used < sizeof (ntsecdesc_t) || 264 iocb.used >= MAX_RAW_SD_SIZE) 265 return (EINVAL); 266 267 /* 268 * Get the buffer contents (security descriptor data) 269 */ 270 mbp = &mb_store; 271 (void) mb_init(mbp); 272 ubuf = (void *)(uintptr_t)iocb.addr; 273 error = mb_put_mem(mbp, ubuf, iocb.used, MB_MUSER); 274 if (error) 275 goto out; 276 277 /* 278 * This does the OTW Set (and maybe open, close) 279 * It clears mb_top when consuming the message. 280 */ 281 error = smbfs_setsd(vp, iocb.selector, &mbp->mb_top, cr); 282 283 out: 284 mb_done(mbp); 285 return (error); 286 287 } 288 289 290 /* 291 * Helper for VOP_GETSECATTR 292 * Call smbfs_getsd, convert NT to ZFS form. 293 */ 294 295 /* ARGSUSED */ 296 int 297 smbfs_getacl(vnode_t *vp, vsecattr_t *vsa, 298 uid_t *uidp, gid_t *gidp, int flag, cred_t *cr) 299 { 300 mdchain_t *mdp, md_store; 301 mblk_t *m = NULL; 302 i_ntsd_t *sd = NULL; 303 uint32_t selector; 304 int error; 305 306 bzero(&md_store, sizeof (md_store)); 307 mdp = &md_store; 308 309 /* 310 * Which parts of the SD we request. 311 * XXX: We need a way to let the caller specify 312 * what parts she wants - i.e. the SACL? 313 * XXX: selector |= SACL_SECURITY_INFORMATION; 314 * Or maybe: if we get access denied, try the 315 * open/fetch again without the SACL bit. 316 */ 317 selector = 0; 318 if (vsa) 319 selector |= DACL_SECURITY_INFORMATION; 320 if (uidp) 321 selector |= OWNER_SECURITY_INFORMATION; 322 if (gidp) 323 selector |= GROUP_SECURITY_INFORMATION; 324 if (selector == 0) 325 return (0); 326 327 /* 328 * This does the OTW Get (and maybe open, close) 329 * Allocates and returns an mblk in &m. 330 */ 331 error = smbfs_getsd(vp, selector, &m, cr); 332 if (error) 333 goto out; 334 /* Note: allocated *m */ 335 md_initm(mdp, m); 336 337 /* 338 * Parse the OtW security descriptor, 339 * storing in our internal form. 340 */ 341 error = md_get_ntsd(mdp, &sd); 342 if (error) 343 goto out; 344 345 /* 346 * Convert the Windows security descriptor to a 347 * ZFS ACL (and owner ID, primary group ID). 348 */ 349 error = smbfs_acl_sd2zfs(sd, vsa, uidp, gidp); 350 351 out: 352 if (sd != NULL) 353 smbfs_acl_free_sd(sd); 354 /* Note: m_freem(m) is done by... */ 355 md_done(mdp); 356 357 return (error); 358 } 359 360 /* 361 * Helper for VOP_SETSECATTR 362 * Convert ZFS to NT form, call smbfs_setsd. 363 */ 364 365 /* ARGSUSED */ 366 int 367 smbfs_setacl(vnode_t *vp, vsecattr_t *vsa, 368 uid_t uid, gid_t gid, int flag, cred_t *cr) 369 { 370 mbchain_t *mbp, mb_store; 371 i_ntsd_t *sd = NULL; 372 uint32_t selector; 373 int error; 374 375 bzero(&mb_store, sizeof (mb_store)); 376 mbp = &mb_store; 377 378 /* 379 * Which parts of the SD we'll modify. 380 * Ditto comments above re. SACL 381 */ 382 selector = 0; 383 if (vsa) 384 selector |= DACL_SECURITY_INFORMATION; 385 if (uid != (uid_t)-1) 386 selector |= OWNER_SECURITY_INFORMATION; 387 if (gid != (gid_t)-1) 388 selector |= GROUP_SECURITY_INFORMATION; 389 if (selector == 0) 390 return (0); 391 392 /* 393 * Convert a ZFS ACL (and owner ID, group ID) 394 * into an NT SD, internal form. 395 */ 396 error = smbfs_acl_zfs2sd(vsa, uid, gid, &sd); 397 if (error) 398 goto out; 399 400 /* 401 * Marshall the internal form SD into an 402 * OtW security descriptor. 403 */ 404 (void) mb_init(mbp); 405 error = mb_put_ntsd(mbp, sd); 406 if (error) 407 goto out; 408 409 /* 410 * This does the OTW Set (and maybe open, close) 411 * It clears mb_top when consuming the message. 412 */ 413 error = smbfs_setsd(vp, selector, &mbp->mb_top, cr); 414 415 out: 416 if (sd != NULL) 417 smbfs_acl_free_sd(sd); 418 mb_done(mbp); 419 return (error); 420 } 421