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 * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 27 */ 28 29 /* 30 * ACL support for smbfs 31 */ 32 33 #include <sys/systm.h> /* bcopy, ... */ 34 #include <sys/errno.h> 35 #include <sys/cred.h> 36 #include <sys/cmn_err.h> 37 #include <sys/kmem.h> 38 #include <sys/sunddi.h> 39 #include <sys/acl.h> 40 #include <sys/vnode.h> 41 #include <sys/vfs.h> 42 #include <sys/byteorder.h> 43 44 #include <netsmb/mchain.h> 45 #include <netsmb/smb.h> 46 #include <netsmb/smb_conn.h> 47 #include <netsmb/smb_osdep.h> 48 #include <netsmb/smb_subr.h> 49 50 #include <smbfs/smbfs.h> 51 #include <smbfs/smbfs_node.h> 52 #include <smbfs/smbfs_subr.h> 53 54 #include <sys/fs/smbfs_ioctl.h> 55 #include <fs/fs_subr.h> 56 #include "smbfs_ntacl.h" 57 58 /* Sanity check SD sizes */ 59 #define MAX_RAW_SD_SIZE 32768 60 #define SMALL_SD_SIZE 1024 61 62 /* 63 * smbfs_getsd() is a common function used by both 64 * smbfs_ioctl SMBFSIO_GETSD and VOP_GETSECATTR. 65 * Handles required rights, tmpopen/tmpclose. 66 * 67 * Note: smbfs_getsd allocates and returns an mblk chain, 68 * which the caller must free. 69 */ 70 static int 71 smbfs_getsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr) 72 { 73 struct smb_cred scred; 74 smbmntinfo_t *smi; 75 smbnode_t *np; 76 smb_fh_t *fid = NULL; 77 uint32_t sdlen = SMALL_SD_SIZE; 78 uint32_t rights = STD_RIGHT_READ_CONTROL_ACCESS; 79 int error; 80 81 if (selector & SACL_SECURITY_INFORMATION) 82 rights |= SEC_RIGHT_SYSTEM_SECURITY; 83 84 np = VTOSMB(vp); 85 smi = VTOSMI(vp); 86 87 smb_credinit(&scred, cr); 88 89 error = smbfs_smb_tmpopen(np, rights, &scred, &fid); 90 if (error) 91 goto out; 92 93 again: 94 /* 95 * This does the OTW Get 96 */ 97 error = smbfs_smb_getsec(smi->smi_share, fid, 98 selector, mp, &sdlen, &scred); 99 /* 100 * Server may give us an error indicating that we 101 * need a larger data buffer to receive the SD, 102 * and the size we'll need. Use the given size, 103 * but only after a sanity check. 104 * 105 * Let's check for specific error values here. 106 * The NT error is: STATUS_BUFFER_TOO_SMALL, 107 * or with old error codes, one of these: 108 * ERRSRV/ERRnoroom, ERRDOS/122, ERRDOS/111 109 * Those are mapped to: EMOREDATA, which is 110 * later converted to E2BIG. 111 */ 112 if (error == E2BIG && 113 sdlen > SMALL_SD_SIZE && 114 sdlen <= MAX_RAW_SD_SIZE) 115 goto again; 116 117 smbfs_smb_tmpclose(np, fid); 118 119 out: 120 smb_credrele(&scred); 121 122 return (error); 123 } 124 125 /* 126 * smbfs_setsd() is a common function used by both 127 * smbfs_ioctl SMBFSIO_SETSD and VOP_SETSECATTR. 128 * Handles required rights, tmpopen/tmpclose. 129 * 130 * Note: smbfs_setsd _consumes_ the passed *mp and 131 * clears the pointer (so the caller won't free it) 132 */ 133 static int 134 smbfs_setsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr) 135 { 136 struct smb_cred scred; 137 smbmntinfo_t *smi; 138 smbnode_t *np; 139 uint32_t rights; 140 smb_fh_t *fid = NULL; 141 int error; 142 143 np = VTOSMB(vp); 144 smi = VTOSMI(vp); 145 146 /* 147 * Which parts of the SD are we setting? 148 * What rights do we need for that? 149 */ 150 if (selector == 0) 151 return (0); 152 153 rights = 0; 154 if (selector & (OWNER_SECURITY_INFORMATION | 155 GROUP_SECURITY_INFORMATION)) 156 rights |= STD_RIGHT_WRITE_OWNER_ACCESS; 157 if (selector & DACL_SECURITY_INFORMATION) 158 rights |= STD_RIGHT_WRITE_DAC_ACCESS; 159 if (selector & SACL_SECURITY_INFORMATION) 160 rights |= SEC_RIGHT_SYSTEM_SECURITY; 161 162 smb_credinit(&scred, cr); 163 164 error = smbfs_smb_tmpopen(np, rights, &scred, &fid); 165 if (error) 166 goto out; 167 168 /* 169 * We're setting the remote ACL now, so 170 * invalidate our cached ACL just in case 171 * the server doesn't do exactly as we ask. 172 */ 173 mutex_enter(&np->r_statelock); 174 np->r_sectime = gethrtime(); 175 mutex_exit(&np->r_statelock); 176 177 /* 178 * This does the OTW Set 179 */ 180 error = smbfs_smb_setsec(smi->smi_share, fid, 181 selector, mp, &scred); 182 183 smbfs_smb_tmpclose(np, fid); 184 185 out: 186 smb_credrele(&scred); 187 188 return (error); 189 } 190 191 /* 192 * Helper for VOP_IOCTL: SMBFSIO_GETSD 193 */ 194 int 195 smbfs_acl_iocget(vnode_t *vp, intptr_t arg, int flag, cred_t *cr) 196 { 197 ioc_sdbuf_t iocb; 198 mdchain_t *mdp, md_store; 199 mblk_t *m; 200 void *ubuf; 201 int error; 202 203 /* 204 * Get the buffer information 205 */ 206 if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag)) 207 return (EFAULT); 208 209 /* 210 * This does the OTW Get (and maybe open, close) 211 * Allocates and returns an mblk in &m. 212 */ 213 error = smbfs_getsd(vp, iocb.selector, &m, cr); 214 if (error) 215 return (error); 216 217 /* 218 * Have m. Must free it before return. 219 */ 220 mdp = &md_store; 221 md_initm(mdp, m); 222 iocb.used = m_fixhdr(m); 223 224 /* 225 * Always copyout the buffer information, 226 * so the user can realloc and try again 227 * after an EOVERFLOW return. 228 */ 229 if (ddi_copyout(&iocb, (void *)arg, sizeof (iocb), flag)) { 230 error = EFAULT; 231 goto out; 232 } 233 234 if (iocb.used > iocb.alloc) { 235 error = EOVERFLOW; 236 goto out; 237 } 238 239 /* 240 * Copyout the buffer contents (SD) 241 */ 242 ubuf = (void *)(uintptr_t)iocb.addr; 243 error = md_get_mem(mdp, ubuf, iocb.used, MB_MUSER); 244 245 out: 246 /* Note: m_freem(m) is done by... */ 247 md_done(mdp); 248 249 return (error); 250 } 251 252 /* 253 * Helper for VOP_IOCTL: SMBFSIO_SETSD 254 */ 255 int 256 smbfs_acl_iocset(vnode_t *vp, intptr_t arg, int flag, cred_t *cr) 257 { 258 ioc_sdbuf_t iocb; 259 mbchain_t *mbp, mb_store; 260 void *ubuf; 261 int error; 262 263 /* 264 * Get the buffer information 265 */ 266 if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag)) 267 return (EFAULT); 268 269 if (iocb.used < sizeof (ntsecdesc_t) || 270 iocb.used >= MAX_RAW_SD_SIZE) 271 return (EINVAL); 272 273 /* 274 * Get the buffer contents (security descriptor data) 275 */ 276 mbp = &mb_store; 277 (void) mb_init(mbp); 278 ubuf = (void *)(uintptr_t)iocb.addr; 279 error = mb_put_mem(mbp, ubuf, iocb.used, MB_MUSER); 280 if (error) 281 goto out; 282 283 /* 284 * This does the OTW Set (and maybe open, close) 285 * It clears mb_top when consuming the message. 286 */ 287 error = smbfs_setsd(vp, iocb.selector, &mbp->mb_top, cr); 288 289 out: 290 mb_done(mbp); 291 return (error); 292 293 } 294 295 /* 296 * Refresh our cached copy of the security attributes 297 */ 298 static int 299 smbfs_acl_refresh(vnode_t *vp, cred_t *cr) 300 { 301 smbnode_t *np; 302 smbmntinfo_t *smi; 303 mdchain_t *mdp, md_store; 304 mblk_t *m = NULL; 305 i_ntsd_t *sd = NULL; 306 vsecattr_t vsa, ovsa; 307 uint32_t selector; 308 uid_t uid; 309 gid_t gid; 310 int error; 311 312 np = VTOSMB(vp); 313 smi = VTOSMI(vp); 314 315 bzero(&md_store, sizeof (md_store)); 316 mdp = &md_store; 317 318 /* 319 * Which parts of the SD we request. 320 * Not getting the SACL for now. 321 */ 322 selector = DACL_SECURITY_INFORMATION | 323 OWNER_SECURITY_INFORMATION | 324 GROUP_SECURITY_INFORMATION; 325 326 /* 327 * This does the OTW Get (and maybe open, close) 328 * Allocates and returns an mblk in &m. 329 */ 330 error = smbfs_getsd(vp, selector, &m, cr); 331 if (error) 332 goto out; 333 /* Note: allocated *m */ 334 md_initm(mdp, m); 335 336 /* 337 * Parse the OtW security descriptor, 338 * storing in our internal form. 339 */ 340 error = md_get_ntsd(mdp, &sd); 341 if (error) 342 goto out; 343 344 /* 345 * Convert the Windows security descriptor to a 346 * ZFS ACL (and owner ID, primary group ID). 347 */ 348 bzero(&vsa, sizeof (vsa)); 349 vsa.vsa_mask = VSA_ACE | VSA_ACECNT; 350 error = smbfs_acl_sd2zfs(sd, &vsa, &uid, &gid); 351 if (error) 352 goto out; 353 354 ASSERT(vsa.vsa_aclentp != NULL); 355 SMBVDEBUG("uid=%u, gid=%u", uid, gid); 356 357 /* 358 * Store the results in r_secattr, n_uid, n_gid 359 */ 360 mutex_enter(&np->r_statelock); 361 ovsa = np->r_secattr; 362 np->r_secattr = vsa; 363 np->n_uid = uid; 364 np->n_gid = gid; 365 /* 366 * ACLs don't change frequently, so cache these 367 * for a relatively long time (ac dir max). 368 */ 369 np->r_sectime = gethrtime() + smi->smi_acdirmax; 370 mutex_exit(&np->r_statelock); 371 372 /* Allocated in: smbfs_acl_sd2zfs */ 373 if (ovsa.vsa_aclentp != NULL) 374 kmem_free(ovsa.vsa_aclentp, ovsa.vsa_aclentsz); 375 376 out: 377 if (sd != NULL) 378 smbfs_acl_free_sd(sd); 379 /* Note: m_freem(m) is done by... */ 380 md_done(mdp); 381 382 return (error); 383 } 384 385 /* 386 * Helper for smbfsgetattr() 387 * 388 * Just refresh the ACL cache if needed, 389 * which updates n_uid/n_gid 390 */ 391 int 392 smbfs_acl_getids(vnode_t *vp, cred_t *cr) 393 { 394 smbnode_t *np; 395 int error; 396 397 np = VTOSMB(vp); 398 399 /* 400 * NB: extended attribute files and directories 401 * do not have ACLs separate from the parent. 402 * Let the caller do ACL fabrication. 403 */ 404 if (np->n_flag & N_XATTR) 405 return (ENOSYS); 406 407 mutex_enter(&np->r_statelock); 408 if (gethrtime() >= np->r_sectime) { 409 /* Need to update r_secattr */ 410 mutex_exit(&np->r_statelock); 411 error = smbfs_acl_refresh(vp, cr); 412 return (error); 413 } 414 mutex_exit(&np->r_statelock); 415 416 return (0); 417 } 418 419 /* 420 * Helper for VOP_GETSECATTR 421 * 422 * Refresh the ACL cache if needed, then 423 * duplicate the requested parts of the vsecattr. 424 */ 425 /* ARGSUSED */ 426 int 427 smbfs_acl_getvsa(vnode_t *vp, vsecattr_t *vsa, 428 int flag, cred_t *cr) 429 { 430 smbnode_t *np; 431 int error; 432 433 np = VTOSMB(vp); 434 435 /* 436 * NB: extended attribute files and directories 437 * do not have ACLs separate from the parent. 438 * Let the caller do ACL fabrication. 439 */ 440 if (np->n_flag & N_XATTR) 441 return (ENOSYS); 442 443 mutex_enter(&np->r_statelock); 444 445 if (np->r_secattr.vsa_aclentp == NULL || 446 gethrtime() >= np->r_sectime) { 447 /* Need to update r_secattr */ 448 mutex_exit(&np->r_statelock); 449 450 error = smbfs_acl_refresh(vp, cr); 451 if (error) 452 return (error); 453 454 mutex_enter(&np->r_statelock); 455 } 456 ASSERT(np->r_secattr.vsa_aclentp != NULL); 457 458 /* 459 * Duplicate requested parts of r_secattr 460 */ 461 462 if (vsa->vsa_mask & VSA_ACECNT) 463 vsa->vsa_aclcnt = np->r_secattr.vsa_aclcnt; 464 465 if (vsa->vsa_mask & VSA_ACE) { 466 vsa->vsa_aclentsz = np->r_secattr.vsa_aclentsz; 467 vsa->vsa_aclentp = kmem_alloc(vsa->vsa_aclentsz, KM_SLEEP); 468 bcopy(np->r_secattr.vsa_aclentp, vsa->vsa_aclentp, 469 vsa->vsa_aclentsz); 470 } 471 472 mutex_exit(&np->r_statelock); 473 return (0); 474 } 475 476 /* 477 * Helper for smbfs_acl_setids, smbfs_acl_setvsa 478 */ 479 static int 480 smbfs_acl_store(vnode_t *vp, vsecattr_t *vsa, uid_t uid, gid_t gid, 481 uint32_t selector, cred_t *cr) 482 { 483 mbchain_t *mbp, mb_store; 484 i_ntsd_t *sd; 485 int error; 486 487 ASSERT(selector != 0); 488 489 sd = NULL; 490 bzero(&mb_store, sizeof (mb_store)); 491 mbp = &mb_store; 492 493 /* 494 * Convert a ZFS ACL (and owner ID, group ID) 495 * into an NT SD, internal form. 496 */ 497 error = smbfs_acl_zfs2sd(vsa, uid, gid, selector, &sd); 498 if (error) 499 goto out; 500 501 /* 502 * Marshall the internal form SD into an 503 * OtW security descriptor. 504 */ 505 (void) mb_init(mbp); 506 error = mb_put_ntsd(mbp, sd); 507 if (error) 508 goto out; 509 510 /* 511 * This does the OTW Set (and maybe open, close) 512 * It clears mb_top when consuming the message. 513 */ 514 error = smbfs_setsd(vp, selector, &mbp->mb_top, cr); 515 516 out: 517 if (sd != NULL) 518 smbfs_acl_free_sd(sd); 519 mb_done(mbp); 520 return (error); 521 } 522 523 /* 524 * Helper for smbfs_setattr() 525 * 526 * Set the passed UID/GID as indicated by va_mask. 527 */ 528 int 529 smbfs_acl_setids(vnode_t *vp, vattr_t *vap, cred_t *cr) 530 { 531 uid_t uid = (uid_t)-1; 532 gid_t gid = (uid_t)-1; 533 uint32_t selector = 0; 534 int error; 535 536 if (vap->va_mask & AT_UID) { 537 selector |= OWNER_SECURITY_INFORMATION; 538 uid = vap->va_uid; 539 } 540 541 if (vap->va_mask & AT_GID) { 542 selector |= GROUP_SECURITY_INFORMATION; 543 gid = vap->va_gid; 544 } 545 546 if (selector == 0) 547 return (0); 548 549 error = smbfs_acl_store(vp, NULL, uid, gid, selector, cr); 550 return (error); 551 } 552 553 /* 554 * Helper for VOP_SETSECATTR 555 * Convert ZFS to NT form, call smbfs_setsd. 556 */ 557 /* ARGSUSED */ 558 int 559 smbfs_acl_setvsa(vnode_t *vp, vsecattr_t *vsa, 560 int flag, cred_t *cr) 561 { 562 uint32_t selector = DACL_SECURITY_INFORMATION; 563 smbnode_t *np = VTOSMB(vp); 564 int error; 565 566 /* 567 * NB: extended attribute files and directories 568 * do not have ACLs separate from the parent. 569 */ 570 if (np->n_flag & N_XATTR) 571 return (ENOSYS); 572 573 /* 574 * When handling ACE_OWNER or ACE_GROUP entries, 575 * we need the current owner and group. 576 */ 577 error = smbfs_acl_getids(vp, cr); 578 if (error) 579 return (error); 580 581 error = smbfs_acl_store(vp, vsa, np->n_uid, np->n_gid, selector, cr); 582 return (error); 583 } 584