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 conversion support for smbfs 29 * (To/from NT/ZFS-style ACLs.) 30 */ 31 32 #include <sys/types.h> 33 #include <sys/errno.h> 34 #include <sys/acl.h> 35 #include <sys/byteorder.h> 36 37 #ifdef _KERNEL 38 39 #include <sys/cred.h> 40 #include <sys/cmn_err.h> 41 #include <sys/kmem.h> 42 #include <sys/sunddi.h> 43 #include <sys/vnode.h> 44 #include <sys/vfs.h> 45 46 #include <sys/kidmap.h> 47 48 #else /* _KERNEL */ 49 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <strings.h> 53 54 #include <idmap.h> 55 56 #endif /* _KERNEL */ 57 58 #include <netsmb/mchain.h> 59 #include <netsmb/smb.h> 60 #include "smbfs_ntacl.h" 61 62 #define NT_SD_REVISION 1 63 #define NT_ACL_REVISION 2 64 65 #ifdef _KERNEL 66 #define MALLOC(size) kmem_alloc(size, KM_SLEEP) 67 #define FREESZ(p, sz) kmem_free(p, sz) 68 #else /* _KERNEL */ 69 #define MALLOC(size) malloc(size) 70 #ifndef lint 71 #define FREESZ(p, sz) free(p) 72 #else /* lint */ 73 /* ARGSUSED */ 74 static void 75 FREESZ(void *p, size_t sz) 76 { 77 free(p); 78 } 79 #endif /* lint */ 80 #endif /* _KERNEL */ 81 82 #define ERRCHK(expr) if ((error = expr) != 0) goto errout 83 84 /* 85 * Security IDentifier (SID) 86 */ 87 static void 88 ifree_sid(i_ntsid_t *sid) 89 { 90 size_t sz; 91 92 if (sid == NULL) 93 return; 94 95 sz = I_SID_SIZE(sid->sid_subauthcount); 96 FREESZ(sid, sz); 97 } 98 99 static int 100 md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp) 101 { 102 i_ntsid_t *sid = NULL; 103 uint8_t revision, subauthcount; 104 uint32_t *subauthp; 105 size_t sidsz; 106 int error, i; 107 108 if ((error = md_get_uint8(mdp, &revision)) != 0) 109 return (error); 110 if ((error = md_get_uint8(mdp, &subauthcount)) != 0) 111 return (error); 112 113 sidsz = I_SID_SIZE(subauthcount); 114 115 if ((sid = MALLOC(sidsz)) == NULL) 116 return (ENOMEM); 117 118 bzero(sid, sidsz); 119 sid->sid_revision = revision; 120 sid->sid_subauthcount = subauthcount; 121 ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM)); 122 123 subauthp = &sid->sid_subauthvec[0]; 124 for (i = 0; i < subauthcount; i++) { 125 ERRCHK(md_get_uint32le(mdp, subauthp)); 126 subauthp++; 127 } 128 129 /* Success! */ 130 *sidp = sid; 131 return (0); 132 133 errout: 134 ifree_sid(sid); 135 return (error); 136 } 137 138 static int 139 mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid) 140 { 141 uint32_t *subauthp; 142 int error, i; 143 144 if (sid == NULL) 145 return (EINVAL); 146 147 ERRCHK(mb_put_uint8(mbp, sid->sid_revision)); 148 ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount)); 149 ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM)); 150 151 subauthp = &sid->sid_subauthvec[0]; 152 for (i = 0; i < sid->sid_subauthcount; i++) { 153 ERRCHK(mb_put_uint32le(mbp, *subauthp)); 154 subauthp++; 155 } 156 157 /* Success! */ 158 return (0); 159 160 errout: 161 return (error); 162 } 163 164 165 /* 166 * Access Control Entry (ACE) 167 */ 168 static void 169 ifree_ace(i_ntace_t *ace) 170 { 171 172 if (ace == NULL) 173 return; 174 175 switch (ace->ace_hdr.ace_type) { 176 case ACCESS_ALLOWED_ACE_TYPE: 177 case ACCESS_DENIED_ACE_TYPE: 178 case SYSTEM_AUDIT_ACE_TYPE: 179 case SYSTEM_ALARM_ACE_TYPE: 180 ifree_sid(ace->ace_v2.ace_sid); 181 FREESZ(ace, sizeof (i_ntace_v2_t)); 182 break; 183 /* other types todo */ 184 default: 185 break; 186 } 187 } 188 189 static int 190 md_get_ace(mdchain_t *mdp, i_ntace_t **acep) 191 { 192 mdchain_t tmp_md; 193 i_ntace_hdr_t ace_hdr; 194 i_ntace_t *ace = NULL; 195 uint16_t alloc_size; 196 int error; 197 198 /* 199 * The ACE is realy variable length, 200 * with format determined by the type. 201 * 202 * There may also be padding after it, so 203 * decode it using a copy of the mdchain, 204 * and then consume the specified length. 205 */ 206 tmp_md = *mdp; 207 208 /* Fixed-size ACE header */ 209 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_type)); 210 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_flags)); 211 ERRCHK(md_get_uint16le(&tmp_md, &ace_hdr.ace_size)); 212 213 switch (ace_hdr.ace_type) { 214 case ACCESS_ALLOWED_ACE_TYPE: 215 case ACCESS_DENIED_ACE_TYPE: 216 case SYSTEM_AUDIT_ACE_TYPE: 217 case SYSTEM_ALARM_ACE_TYPE: 218 alloc_size = sizeof (i_ntace_v2_t); 219 if ((ace = MALLOC(alloc_size)) == NULL) 220 return (ENOMEM); 221 bzero(ace, alloc_size); 222 /* ACE header */ 223 ace->ace_hdr.ace_type = ace_hdr.ace_type; 224 ace->ace_hdr.ace_flags = ace_hdr.ace_flags; 225 ace->ace_hdr.ace_size = alloc_size; 226 /* Type-specific data. */ 227 ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_v2.ace_rights)); 228 ERRCHK(md_get_sid(&tmp_md, &ace->ace_v2.ace_sid)); 229 break; 230 231 /* other types todo */ 232 default: 233 error = EIO; 234 goto errout; 235 } 236 237 /* Now actually consume ace_hdr.ace_size */ 238 ERRCHK(md_get_mem(mdp, NULL, ace_hdr.ace_size, MB_MSYSTEM)); 239 240 /* Success! */ 241 *acep = ace; 242 return (0); 243 244 errout: 245 ifree_ace(ace); 246 return (error); 247 } 248 249 static int 250 mb_put_ace(mbchain_t *mbp, i_ntace_t *ace) 251 { 252 int cnt0, error; 253 uint16_t ace_len, *ace_len_p; 254 255 if (ace == NULL) 256 return (EINVAL); 257 258 cnt0 = mbp->mb_count; 259 260 /* 261 * Put the (fixed-size) ACE header 262 * Will fill in the length later. 263 */ 264 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_type)); 265 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_flags)); 266 ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p)); 267 if (ace_len_p == NULL) { 268 error = ENOMEM; 269 goto errout; 270 } 271 272 switch (ace->ace_hdr.ace_type) { 273 case ACCESS_ALLOWED_ACE_TYPE: 274 case ACCESS_DENIED_ACE_TYPE: 275 case SYSTEM_AUDIT_ACE_TYPE: 276 case SYSTEM_ALARM_ACE_TYPE: 277 /* Put type-specific data. */ 278 ERRCHK(mb_put_uint32le(mbp, ace->ace_v2.ace_rights)); 279 ERRCHK(mb_put_sid(mbp, ace->ace_v2.ace_sid)); 280 break; 281 282 /* other types todo */ 283 default: 284 error = EIO; 285 goto errout; 286 } 287 288 /* Fill in the (OtW) ACE length. */ 289 ace_len = mbp->mb_count - cnt0; 290 *ace_len_p = htoles(ace_len); 291 292 /* Success! */ 293 return (0); 294 295 errout: 296 return (error); 297 } 298 299 300 /* 301 * Access Control List (ACL) 302 */ 303 304 /* Not an OTW structure, so size can be at our convenience. */ 305 #define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *)) 306 307 static void 308 ifree_acl(i_ntacl_t *acl) 309 { 310 i_ntace_t **acep; 311 size_t sz; 312 int i; 313 314 if (acl == NULL) 315 return; 316 317 acep = &acl->acl_acevec[0]; 318 for (i = 0; i < acl->acl_acecount; i++) { 319 ifree_ace(*acep); 320 acep++; 321 } 322 sz = I_ACL_SIZE(acl->acl_acecount); 323 FREESZ(acl, sz); 324 } 325 326 static int 327 md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp) 328 { 329 i_ntacl_t *acl = NULL; 330 i_ntace_t **acep; 331 uint8_t revision; 332 uint16_t acl_len, acecount; 333 size_t aclsz; 334 int i, error; 335 336 if ((error = md_get_uint8(mdp, &revision)) != 0) 337 return (error); 338 if ((error = md_get_uint8(mdp, NULL)) != 0) /* pad1 */ 339 return (error); 340 if ((error = md_get_uint16le(mdp, &acl_len)) != 0) 341 return (error); 342 if ((error = md_get_uint16le(mdp, &acecount)) != 0) 343 return (error); 344 if ((error = md_get_uint16le(mdp, NULL)) != 0) /* pad2 */ 345 return (error); 346 347 aclsz = I_ACL_SIZE(acecount); 348 if ((acl = MALLOC(aclsz)) == NULL) 349 return (ENOMEM); 350 bzero(acl, aclsz); 351 acl->acl_revision = revision; 352 acl->acl_acecount = acecount; 353 354 acep = &acl->acl_acevec[0]; 355 for (i = 0; i < acl->acl_acecount; i++) { 356 ERRCHK(md_get_ace(mdp, acep)); 357 acep++; 358 } 359 /* 360 * There may be more data here, but 361 * the caller takes care of that. 362 */ 363 364 /* Success! */ 365 *aclp = acl; 366 return (0); 367 368 errout: 369 ifree_acl(acl); 370 return (error); 371 } 372 373 static int 374 mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl) 375 { 376 i_ntace_t **acep; 377 uint16_t acl_len, *acl_len_p; 378 int i, cnt0, error; 379 380 cnt0 = mbp->mb_count; 381 382 ERRCHK(mb_put_uint8(mbp, acl->acl_revision)); 383 ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */ 384 acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p)); 385 if (acl_len_p == NULL) { 386 error = ENOMEM; 387 goto errout; 388 } 389 ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount)); 390 ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */ 391 392 acep = &acl->acl_acevec[0]; 393 for (i = 0; i < acl->acl_acecount; i++) { 394 ERRCHK(mb_put_ace(mbp, *acep)); 395 acep++; 396 } 397 398 /* Fill in acl_len_p */ 399 acl_len = mbp->mb_count - cnt0; 400 *acl_len_p = htoles(acl_len); 401 402 /* Success! */ 403 return (0); 404 405 errout: 406 return (error); 407 } 408 409 410 /* 411 * Security Descriptor 412 */ 413 void 414 smbfs_acl_free_sd(i_ntsd_t *sd) 415 { 416 417 if (sd == NULL) 418 return; 419 420 ifree_sid(sd->sd_owner); 421 ifree_sid(sd->sd_group); 422 ifree_acl(sd->sd_sacl); 423 ifree_acl(sd->sd_dacl); 424 425 FREESZ(sd, sizeof (*sd)); 426 } 427 428 /* 429 * Import a raw SD (mb chain) into "internal" form. 430 * (like "absolute" form per. NT docs) 431 * Returns allocated data in sdp 432 * 433 * Note: does NOT consume all the mdp data, so the 434 * caller has to take care of that if necessary. 435 */ 436 int 437 md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp) 438 { 439 i_ntsd_t *sd = NULL; 440 mdchain_t top_md, tmp_md; 441 uint32_t owneroff, groupoff, sacloff, dacloff; 442 int error; 443 444 if ((sd = MALLOC(sizeof (*sd))) == NULL) 445 return (ENOMEM); 446 bzero(sd, sizeof (*sd)); 447 448 /* 449 * Offsets below are relative to this point, 450 * so save the mdp state for use below. 451 */ 452 top_md = *mdp; 453 454 ERRCHK(md_get_uint8(mdp, &sd->sd_revision)); 455 ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl)); 456 ERRCHK(md_get_uint16le(mdp, &sd->sd_flags)); 457 ERRCHK(md_get_uint32le(mdp, &owneroff)); 458 ERRCHK(md_get_uint32le(mdp, &groupoff)); 459 ERRCHK(md_get_uint32le(mdp, &sacloff)); 460 ERRCHK(md_get_uint32le(mdp, &dacloff)); 461 462 /* 463 * The SD is "self-relative" on the wire, 464 * but not after this decodes it. 465 */ 466 sd->sd_flags &= ~SD_SELF_RELATIVE; 467 468 /* 469 * For each section make a temporary copy of the 470 * top_md state, advance to the given offset, and 471 * pass that to the lower md_get_xxx functions. 472 * These could be marshalled in any order, but 473 * are normally found in the order shown here. 474 */ 475 if (sacloff) { 476 tmp_md = top_md; 477 md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM); 478 ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl)); 479 } 480 if (dacloff) { 481 tmp_md = top_md; 482 md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM); 483 ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl)); 484 } 485 if (owneroff) { 486 tmp_md = top_md; 487 md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM); 488 ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner)); 489 } 490 if (groupoff) { 491 tmp_md = top_md; 492 md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM); 493 ERRCHK(md_get_sid(&tmp_md, &sd->sd_group)); 494 } 495 496 /* Success! */ 497 *sdp = sd; 498 return (0); 499 500 errout: 501 smbfs_acl_free_sd(sd); 502 return (error); 503 } 504 505 /* 506 * Export an "internal" SD into an raw SD (mb chain). 507 * (a.k.a "self-relative" form per. NT docs) 508 * Returns allocated mbchain in mbp. 509 */ 510 int 511 mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd) 512 { 513 uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp; 514 uint32_t owneroff, groupoff, sacloff, dacloff; 515 uint16_t flags; 516 int cnt0, error; 517 518 cnt0 = mbp->mb_count; 519 owneroff = groupoff = sacloff = dacloff = 0; 520 521 /* The SD is "self-relative" on the wire. */ 522 flags = sd->sd_flags | SD_SELF_RELATIVE; 523 524 ERRCHK(mb_put_uint8(mbp, sd->sd_revision)); 525 ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl)); 526 ERRCHK(mb_put_uint16le(mbp, flags)); 527 528 owneroffp = mb_reserve(mbp, sizeof (*owneroffp)); 529 groupoffp = mb_reserve(mbp, sizeof (*groupoffp)); 530 sacloffp = mb_reserve(mbp, sizeof (*sacloffp)); 531 dacloffp = mb_reserve(mbp, sizeof (*dacloffp)); 532 if (owneroffp == NULL || groupoffp == NULL || 533 sacloffp == NULL || dacloffp == NULL) { 534 error = ENOMEM; 535 goto errout; 536 } 537 538 /* 539 * These could be marshalled in any order, but 540 * are normally found in the order shown here. 541 */ 542 if (sd->sd_sacl) { 543 sacloff = mbp->mb_count - cnt0; 544 ERRCHK(mb_put_acl(mbp, sd->sd_sacl)); 545 } 546 if (sd->sd_dacl) { 547 dacloff = mbp->mb_count - cnt0; 548 ERRCHK(mb_put_acl(mbp, sd->sd_dacl)); 549 } 550 if (sd->sd_owner) { 551 owneroff = mbp->mb_count - cnt0; 552 ERRCHK(mb_put_sid(mbp, sd->sd_owner)); 553 } 554 if (sd->sd_group) { 555 groupoff = mbp->mb_count - cnt0; 556 ERRCHK(mb_put_sid(mbp, sd->sd_group)); 557 } 558 559 /* Fill in the offsets */ 560 *owneroffp = htolel(owneroff); 561 *groupoffp = htolel(groupoff); 562 *sacloffp = htolel(sacloff); 563 *dacloffp = htolel(dacloff); 564 565 /* Success! */ 566 return (0); 567 568 errout: 569 return (error); 570 } 571 572 /* 573 * ================================================================ 574 * Support for ACL fetch, including conversions 575 * from Windows ACLs to NFSv4-style ACLs. 576 * ================================================================ 577 */ 578 579 #define GENERIC_RIGHTS_MASK \ 580 (GENERIC_RIGHT_READ_ACCESS | GENERIC_RIGHT_WRITE_ACCESS |\ 581 GENERIC_RIGHT_EXECUTE_ACCESS | GENERIC_RIGHT_ALL_ACCESS) 582 583 /* 584 * Table for converting NT GENERIC_RIGHT_... to specific rights 585 * appropriate for objects of type file. 586 */ 587 struct gen2fsr { 588 uint32_t gf_generic; 589 uint32_t gf_specific; 590 }; 591 static const struct gen2fsr 592 smbfs_gen2fsr[] = { 593 { 594 GENERIC_RIGHT_READ_ACCESS, 595 STD_RIGHT_SYNCHRONIZE_ACCESS | 596 STD_RIGHT_READ_CONTROL_ACCESS | 597 SA_RIGHT_FILE_READ_ATTRIBUTES | 598 SA_RIGHT_FILE_READ_EA | 599 SA_RIGHT_FILE_READ_DATA }, 600 { 601 GENERIC_RIGHT_WRITE_ACCESS, 602 STD_RIGHT_SYNCHRONIZE_ACCESS | 603 STD_RIGHT_READ_CONTROL_ACCESS | 604 SA_RIGHT_FILE_WRITE_ATTRIBUTES | 605 SA_RIGHT_FILE_WRITE_EA | 606 SA_RIGHT_FILE_APPEND_DATA | 607 SA_RIGHT_FILE_WRITE_DATA }, 608 { 609 GENERIC_RIGHT_EXECUTE_ACCESS, 610 STD_RIGHT_SYNCHRONIZE_ACCESS | 611 STD_RIGHT_READ_CONTROL_ACCESS | 612 SA_RIGHT_FILE_READ_ATTRIBUTES | 613 SA_RIGHT_FILE_EXECUTE }, 614 { 615 GENERIC_RIGHT_ALL_ACCESS, 616 STD_RIGHT_SYNCHRONIZE_ACCESS | 617 STD_RIGHT_WRITE_OWNER_ACCESS | 618 STD_RIGHT_WRITE_DAC_ACCESS | 619 STD_RIGHT_READ_CONTROL_ACCESS | 620 STD_RIGHT_DELETE_ACCESS | 621 SA_RIGHT_FILE_ALL_ACCESS }, 622 { 0, 0 } 623 }; 624 625 /* 626 * Table for translating ZFS ACE flags to NT ACE flags. 627 * The low four bits are the same, but not others. 628 */ 629 struct zaf2naf { 630 uint16_t za_flag; 631 uint8_t na_flag; 632 }; 633 static const struct zaf2naf 634 smbfs_zaf2naf[] = { 635 { ACE_FILE_INHERIT_ACE, OBJECT_INHERIT_ACE_FLAG }, 636 { ACE_DIRECTORY_INHERIT_ACE, CONTAINER_INHERIT_ACE_FLAG }, 637 { ACE_NO_PROPAGATE_INHERIT_ACE, NO_PROPAGATE_INHERIT_ACE_FLAG }, 638 { ACE_INHERIT_ONLY_ACE, INHERIT_ONLY_ACE_FLAG }, 639 { ACE_INHERITED_ACE, INHERITED_ACE_FLAG }, 640 { ACE_SUCCESSFUL_ACCESS_ACE_FLAG, SUCCESSFUL_ACCESS_ACE_FLAG }, 641 { ACE_FAILED_ACCESS_ACE_FLAG, FAILED_ACCESS_ACE_FLAG }, 642 { 0, 0 } 643 }; 644 645 /* 646 * Convert an NT SID to a string. Optionally return the 647 * last sub-authority (or "relative ID" -- RID) in *ridp 648 * and truncate the output string after the domain part. 649 * If ridp==NULL, the output string is the whole SID, 650 * including both the domain and RID. 651 * 652 * Return length written, or -1 on error. 653 */ 654 int 655 smbfs_sid2str(i_ntsid_t *sid, 656 char *obuf, size_t osz, uint32_t *ridp) 657 { 658 char *s = obuf; 659 uint64_t auth = 0; 660 uint_t i, n; 661 uint32_t subs, *ip; 662 663 n = snprintf(s, osz, "S-%u", sid->sid_revision); 664 if (n > osz) 665 return (-1); 666 s += n; osz -= n; 667 668 for (i = 0; i < 6; i++) 669 auth = (auth << 8) | sid->sid_authority[i]; 670 n = snprintf(s, osz, "-%llu", (u_longlong_t)auth); 671 if (n > osz) 672 return (-1); 673 s += n; osz -= n; 674 675 subs = sid->sid_subauthcount; 676 if (subs < 1 || subs > 15) 677 return (-1); 678 if (ridp) 679 subs--; 680 681 ip = &sid->sid_subauthvec[0]; 682 for (; subs; subs--, ip++) { 683 n = snprintf(s, osz, "-%u", *ip); 684 if (n > osz) 685 return (-1); 686 s += n; osz -= n; 687 } 688 if (ridp) 689 *ridp = *ip; 690 691 /* LINTED E_PTRDIFF_OVERFLOW */ 692 return (s - obuf); 693 } 694 695 /* 696 * Our interface to the idmap service. 697 * 698 * The idmap API is _almost_ the same between 699 * kernel and user-level. But not quite... 700 * Hope this improves readability below. 701 */ 702 #ifdef _KERNEL 703 704 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \ 705 kidmap_batch_getuidbysid(GH, SPP, RID, UIDP, SP) 706 707 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \ 708 kidmap_batch_getgidbysid(GH, SPP, RID, GIDP, SP) 709 710 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \ 711 kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) 712 713 #define I_getmappings kidmap_get_mappings 714 715 #else /* _KERNEL */ 716 717 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \ 718 idmap_get_uidbysid(GH, SPP, RID, 0, UIDP, SP) 719 720 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \ 721 idmap_get_gidbysid(GH, SPP, RID, 0, GIDP, SP) 722 723 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \ 724 idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP) 725 726 #define I_getmappings idmap_get_mappings 727 728 #endif /* _KERNEL */ 729 730 731 /* 732 * The idmap request types, chosen so they also 733 * match the values returned in mi_isuser. 734 */ 735 #define IDM_TYPE_ANY -1 736 #define IDM_TYPE_GROUP 0 737 #define IDM_TYPE_USER 1 738 739 /* 740 * A sentinel value for mi_isuser (below) to indicate 741 * that the SID is the well-known "Everyone" (S-1-1-0). 742 * The idmap library only uses -1, 0, 1, so this value 743 * is arbitrary but must not overlap w/ idmap values. 744 * XXX: Could use a way for idmap to tell us when 745 * it recognizes this well-known SID. 746 */ 747 #define IDM_EVERYONE 11 748 749 struct mapinfo2uid { 750 uid_t mi_uid; /* or gid, or pid */ 751 int mi_isuser; /* IDM_TYPE */ 752 idmap_stat mi_status; 753 }; 754 755 /* 756 * Build an idmap request. Cleanup is 757 * handled by the caller (error or not) 758 */ 759 static int 760 mkrq_idmap_sid2ux( 761 idmap_get_handle_t *idmap_gh, 762 struct mapinfo2uid *mip, 763 i_ntsid_t *sid, 764 int req_type) 765 { 766 char strbuf[256]; 767 char *sid_prefix; 768 uint32_t rid; 769 idmap_stat idms; 770 771 if (smbfs_sid2str(sid, strbuf, sizeof (strbuf), &rid) < 0) 772 return (EINVAL); 773 sid_prefix = strbuf; 774 775 /* 776 * Give the "Everyone" group special treatment. 777 */ 778 if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) { 779 /* This is "Everyone" */ 780 mip->mi_uid = (uid_t)-1; 781 mip->mi_isuser = IDM_EVERYONE; 782 mip->mi_status = 0; 783 return (0); 784 } 785 786 switch (req_type) { 787 788 case IDM_TYPE_USER: 789 mip->mi_isuser = req_type; 790 idms = I_getuidbysid(idmap_gh, sid_prefix, rid, 791 &mip->mi_uid, &mip->mi_status); 792 break; 793 794 case IDM_TYPE_GROUP: 795 mip->mi_isuser = req_type; 796 idms = I_getgidbysid(idmap_gh, sid_prefix, rid, 797 &mip->mi_uid, &mip->mi_status); 798 break; 799 800 case IDM_TYPE_ANY: 801 idms = I_getpidbysid(idmap_gh, sid_prefix, rid, 802 &mip->mi_uid, &mip->mi_isuser, &mip->mi_status); 803 break; 804 805 default: 806 idms = IDMAP_ERR_OTHER; 807 break; 808 } 809 810 if (idms != IDMAP_SUCCESS) 811 return (EINVAL); 812 813 return (0); 814 } 815 816 /* 817 * Convert an NT ACE to a ZFS ACE. 818 * ACE type was already validated. 819 */ 820 static void 821 ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo2uid *mip) 822 { 823 const struct zaf2naf *znaf; 824 uid_t zwho; 825 uint32_t zamask; 826 uint16_t zflags; 827 828 /* 829 * Set the "ID type" flags in the ZFS ace flags. 830 */ 831 zflags = 0; 832 switch (mip->mi_isuser) { 833 case IDM_EVERYONE: 834 zflags = ACE_EVERYONE; 835 zwho = (uid_t)-1; 836 break; 837 838 case IDM_TYPE_GROUP: /* it's a GID */ 839 zflags = ACE_IDENTIFIER_GROUP; 840 zwho = mip->mi_uid; 841 break; 842 843 default: 844 case IDM_TYPE_USER: /* it's a UID */ 845 zflags = 0; 846 zwho = mip->mi_uid; 847 break; 848 } 849 850 /* 851 * Translate NT ACE flags to ZFS ACE flags. 852 */ 853 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++) 854 if (ntace->ace_hdr.ace_flags & znaf->na_flag) 855 zflags |= znaf->za_flag; 856 857 /* 858 * The "normal" access mask bits are the same, but 859 * if the ACE has any GENERIC_RIGHT_... convert those 860 * to specific rights. GENERIC bits are rarely seen, 861 * but reportedly can happen with inherit-only ACEs. 862 */ 863 zamask = ntace->ace_v2.ace_rights & ACE_ALL_PERMS; 864 if (ntace->ace_v2.ace_rights & GENERIC_RIGHTS_MASK) { 865 const struct gen2fsr *gf; 866 for (gf = smbfs_gen2fsr; gf->gf_generic; gf++) 867 if (ntace->ace_v2.ace_rights & gf->gf_generic) 868 zamask |= gf->gf_specific; 869 } 870 871 /* 872 * Fill in the ZFS-style ACE 873 */ 874 zacep->a_who = zwho; 875 zacep->a_access_mask = zamask; 876 zacep->a_flags = zflags; 877 zacep->a_type = ntace->ace_hdr.ace_type; 878 } 879 880 /* 881 * Convert an internal SD to a ZFS-style ACL. 882 * Note optional args: vsa/acl, uidp, gidp. 883 * 884 * This makes two passes over the SD, the first building a 885 * "batch" request for idmap with results in mapinfo, the 886 * second building a ZFS-style ACL using the idmap results. 887 */ 888 int 889 smbfs_acl_sd2zfs( 890 i_ntsd_t *sd, 891 #ifdef _KERNEL 892 vsecattr_t *acl_info, 893 #else /* _KERNEL */ 894 acl_t *acl_info, 895 #endif /* _KERNEL */ 896 uid_t *uidp, gid_t *gidp) 897 { 898 struct mapinfo2uid *mip, *mapinfo = NULL; 899 int error, i, mapcnt, zacecnt, zacl_size; 900 ace_t *zacep0, *zacep; 901 uid_t own_uid = (uid_t)-1; 902 gid_t own_gid = (gid_t)-1; 903 i_ntacl_t *ntacl; 904 i_ntace_t **ntacep; 905 #ifndef _KERNEL 906 idmap_handle_t *idmap_h = NULL; 907 #endif /* _KERNEL */ 908 idmap_get_handle_t *idmap_gh = NULL; 909 idmap_stat idms; 910 911 /* 912 * sanity checks 913 */ 914 if (acl_info) { 915 #ifndef _KERNEL 916 if (acl_info->acl_type != ACE_T || 917 acl_info->acl_aclp != NULL || 918 acl_info->acl_entry_size != sizeof (ace_t)) 919 return (EINVAL); 920 #endif /* _KERNEL */ 921 if ((sd->sd_flags & SD_DACL_PRESENT) == 0) 922 return (EINVAL); 923 } 924 925 /* 926 * How many SID mappings will we need? 927 */ 928 mapcnt = 0; 929 if (sd->sd_owner) 930 mapcnt++; 931 if (sd->sd_group) 932 mapcnt++; 933 if ((sd->sd_flags & SD_SACL_PRESENT) && 934 (sd->sd_sacl != NULL)) 935 mapcnt += sd->sd_sacl->acl_acecount; 936 if ((sd->sd_flags & SD_DACL_PRESENT) && 937 (sd->sd_dacl != NULL)) 938 mapcnt += sd->sd_dacl->acl_acecount; 939 if (mapcnt == 0) { 940 /* 941 * We have a NULL DACL, SACL, and don't 942 * have an owner or group, so there's no 943 * idmap work to do. This is very rare, 944 * so rather than complicate things below, 945 * pretend we need one mapping slot. 946 */ 947 mapcnt = 1; 948 } 949 950 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo)); 951 if (mapinfo == NULL) { 952 error = ENOMEM; 953 goto errout; 954 } 955 bzero(mapinfo, mapcnt * sizeof (*mapinfo)); 956 957 958 /* 959 * Get an imap "batch" request handle. 960 */ 961 #ifdef _KERNEL 962 idmap_gh = kidmap_get_create(curproc->p_zone); 963 #else /* _KERNEL */ 964 idms = idmap_init(&idmap_h); 965 if (idms != IDMAP_SUCCESS) { 966 error = ENOTACTIVE; 967 goto errout; 968 } 969 idms = idmap_get_create(idmap_h, &idmap_gh); 970 if (idms != IDMAP_SUCCESS) { 971 error = ENOTACTIVE; 972 goto errout; 973 } 974 #endif /* _KERNEL */ 975 976 /* 977 * Build our request to the idmap deamon, 978 * getting Unix IDs for every SID. 979 */ 980 mip = mapinfo; 981 if (sd->sd_owner) { 982 error = mkrq_idmap_sid2ux(idmap_gh, mip, 983 sd->sd_owner, IDM_TYPE_USER); 984 if (error) 985 goto errout; 986 mip++; 987 } 988 if (sd->sd_group) { 989 error = mkrq_idmap_sid2ux(idmap_gh, mip, 990 sd->sd_group, IDM_TYPE_GROUP); 991 if (error) 992 goto errout; 993 mip++; 994 } 995 if ((sd->sd_flags & SD_SACL_PRESENT) && 996 (sd->sd_sacl != NULL)) { 997 ntacl = sd->sd_sacl; 998 ntacep = &ntacl->acl_acevec[0]; 999 for (i = 0; i < ntacl->acl_acecount; i++) { 1000 error = mkrq_idmap_sid2ux(idmap_gh, mip, 1001 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY); 1002 if (error) 1003 goto errout; 1004 ntacep++; 1005 mip++; 1006 } 1007 } 1008 if ((sd->sd_flags & SD_DACL_PRESENT) && 1009 (sd->sd_dacl != NULL)) { 1010 ntacl = sd->sd_dacl; 1011 ntacep = &ntacl->acl_acevec[0]; 1012 for (i = 0; i < ntacl->acl_acecount; i++) { 1013 error = mkrq_idmap_sid2ux(idmap_gh, mip, 1014 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY); 1015 if (error) 1016 goto errout; 1017 ntacep++; 1018 mip++; 1019 } 1020 } 1021 1022 if (mip != mapinfo) { 1023 idms = I_getmappings(idmap_gh); 1024 if (idms != IDMAP_SUCCESS) { 1025 /* creative error choice */ 1026 error = EIDRM; 1027 goto errout; 1028 } 1029 } 1030 1031 /* 1032 * With any luck, we now have Unix user/group IDs 1033 * for every Windows SID in the security descriptor. 1034 * The remaining work is just format conversion. 1035 */ 1036 mip = mapinfo; 1037 if (sd->sd_owner) { 1038 own_uid = mip->mi_uid; 1039 mip++; 1040 } 1041 if (sd->sd_group) { 1042 own_gid = mip->mi_uid; 1043 mip++; 1044 } 1045 1046 if (uidp) 1047 *uidp = own_uid; 1048 if (gidp) 1049 *gidp = own_gid; 1050 1051 if (acl_info == NULL) { 1052 /* Caller only wanted uid/gid */ 1053 goto done; 1054 } 1055 1056 /* 1057 * Build the ZFS-style ACL 1058 * First, allocate the most ZFS ACEs we'll need. 1059 */ 1060 zacecnt = 0; 1061 if ((sd->sd_flags & SD_SACL_PRESENT) && 1062 (sd->sd_sacl != NULL)) 1063 zacecnt += sd->sd_sacl->acl_acecount; 1064 1065 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */ 1066 if ((sd->sd_dacl != NULL) && 1067 (sd->sd_dacl->acl_acecount > 0)) { 1068 zacecnt += sd->sd_dacl->acl_acecount; 1069 } else { 1070 /* 1071 * DACL is NULL or empty. Either way, 1072 * we'll need to add a ZFS ACE below. 1073 */ 1074 zacecnt++; 1075 } 1076 zacl_size = zacecnt * sizeof (ace_t); 1077 zacep0 = MALLOC(zacl_size); 1078 if (zacep0 == NULL) { 1079 error = ENOMEM; 1080 goto errout; 1081 } 1082 zacep = zacep0; 1083 1084 if ((sd->sd_flags & SD_SACL_PRESENT) && 1085 (sd->sd_sacl != NULL)) { 1086 ntacl = sd->sd_sacl; 1087 ntacep = &ntacl->acl_acevec[0]; 1088 for (i = 0; i < ntacl->acl_acecount; i++) { 1089 ntace2zace(zacep, *ntacep, mip); 1090 zacep++; 1091 ntacep++; 1092 mip++; 1093 } 1094 } 1095 1096 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */ 1097 if (sd->sd_dacl != NULL) { 1098 ntacl = sd->sd_dacl; 1099 ntacep = &ntacl->acl_acevec[0]; 1100 for (i = 0; i < ntacl->acl_acecount; i++) { 1101 ntace2zace(zacep, *ntacep, mip); 1102 zacep++; 1103 ntacep++; 1104 mip++; 1105 } 1106 } 1107 if (sd->sd_dacl == NULL) { 1108 /* 1109 * The SD has a NULL DACL. That means 1110 * everyone@, full-control 1111 */ 1112 zacep->a_who = (uid_t)-1; 1113 zacep->a_access_mask = ACE_ALL_PERMS; 1114 zacep->a_flags = ACE_EVERYONE; 1115 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE; 1116 } else if (sd->sd_dacl->acl_acecount == 0) { 1117 /* 1118 * The SD has an Empty DACL. We need 1119 * at least one ACE, so add one giving 1120 * the owner the usual implied access. 1121 */ 1122 zacep->a_who = (uid_t)-1; 1123 zacep->a_access_mask = ACE_READ_ATTRIBUTES | \ 1124 ACE_READ_ACL | ACE_WRITE_ACL; 1125 zacep->a_flags = ACE_OWNER; 1126 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE; 1127 } 1128 1129 #ifdef _KERNEL 1130 acl_info->vsa_aclcnt = zacecnt; 1131 acl_info->vsa_aclentp = zacep0; 1132 acl_info->vsa_aclentsz = zacl_size; 1133 #else /* _KERNEL */ 1134 acl_info->acl_cnt = zacecnt; 1135 acl_info->acl_aclp = zacep0; 1136 #endif /* _KERNEL */ 1137 1138 done: 1139 error = 0; 1140 1141 errout: 1142 if (mapinfo != NULL) 1143 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo)); 1144 #ifdef _KERNEL 1145 if (idmap_gh != NULL) 1146 kidmap_get_destroy(idmap_gh); 1147 #else /* _KERNEL */ 1148 if (idmap_gh != NULL) 1149 idmap_get_destroy(idmap_gh); 1150 if (idmap_h != NULL) 1151 (void) idmap_fini(idmap_h); 1152 #endif /* _KERNEL */ 1153 1154 return (error); 1155 } 1156 1157 1158 /* 1159 * ================================================================ 1160 * Support for ACL store, including conversions 1161 * from NFSv4-style ACLs to Windows ACLs. 1162 * ================================================================ 1163 */ 1164 1165 /* 1166 * Convert a "sid-prefix" string plus RID into an NT SID. 1167 * 1168 * If successful, sets *osid and returns zero, 1169 * otherwise returns an errno value. 1170 */ 1171 int 1172 smbfs_str2sid(const char *sid_prefix, uint32_t *ridp, i_ntsid_t **osidp) 1173 { 1174 i_ntsid_t *sid = NULL; 1175 u_longlong_t auth = 0; 1176 ulong_t sa; 1177 uint8_t sacnt; 1178 const char *p; 1179 char *np; 1180 size_t size; 1181 int i; 1182 int err; 1183 1184 if (sid_prefix == NULL) 1185 return (EINVAL); 1186 1187 p = sid_prefix; 1188 if (strncmp(p, "S-1-", 4) != 0) 1189 return (EINVAL); 1190 p += 4; 1191 1192 /* Parse the "authority" */ 1193 #ifdef _KERNEL 1194 err = ddi_strtoull(p, &np, 10, &auth); 1195 if (err != 0) 1196 return (err); 1197 #else /* _KERNEL */ 1198 auth = strtoull(p, &np, 10); 1199 if (p == np) 1200 return (EINVAL); 1201 #endif /* _KERNEL */ 1202 1203 /* 1204 * Count the sub-authorities. Here, np points to 1205 * the "-" before the first sub-authority. 1206 */ 1207 sacnt = 0; 1208 for (p = np; *p; p++) { 1209 if (*p == '-') 1210 sacnt++; 1211 } 1212 if (ridp != NULL) 1213 sacnt++; 1214 1215 /* Allocate the internal SID. */ 1216 size = I_SID_SIZE(sacnt); 1217 sid = MALLOC(size); 1218 if (sid == NULL) 1219 return (ENOMEM); 1220 bzero(sid, size); 1221 1222 /* Fill it in. */ 1223 sid->sid_revision = 1; 1224 sid->sid_subauthcount = sacnt; 1225 for (i = 5; i >= 0; i--) { 1226 sid->sid_authority[i] = auth & 0xFF; 1227 auth = auth >> 8; 1228 } 1229 1230 err = EINVAL; 1231 if (ridp != NULL) 1232 sacnt--; /* Last SA not from string */ 1233 p = np; 1234 for (i = 0; i < sacnt; i++) { 1235 if (*p != '-') { 1236 err = EINVAL; 1237 goto out; 1238 } 1239 p++; 1240 #ifdef _KERNEL 1241 err = ddi_strtoul(p, &np, 10, &sa); 1242 if (err != 0) 1243 goto out; 1244 #else /* _KERNEL */ 1245 sa = strtoul(p, &np, 10); 1246 if (p == np) { 1247 err = EINVAL; 1248 goto out; 1249 } 1250 #endif /* _KERNEL */ 1251 sid->sid_subauthvec[i] = (uint32_t)sa; 1252 p = np; 1253 } 1254 if (*p != '\0') 1255 goto out; 1256 if (ridp != NULL) 1257 sid->sid_subauthvec[i] = *ridp; 1258 err = 0; 1259 1260 out: 1261 if (err) 1262 FREESZ(sid, size); 1263 else 1264 *osidp = sid; 1265 1266 return (err); 1267 } 1268 1269 /* 1270 * The idmap API is _almost_ the same between 1271 * kernel and user-level. But not quite... 1272 * Hope this improves readability below. 1273 */ 1274 #ifdef _KERNEL 1275 1276 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \ 1277 kidmap_batch_getsidbyuid(GH, UID, SPP, RP, ST) 1278 1279 #define I_getsidbygid(GH, GID, SPP, RP, ST) \ 1280 kidmap_batch_getsidbygid(GH, GID, SPP, RP, ST) 1281 1282 #else /* _KERNEL */ 1283 1284 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \ 1285 idmap_get_sidbyuid(GH, UID, 0, SPP, RP, ST) 1286 1287 #define I_getsidbygid(GH, GID, SPP, RP, ST) \ 1288 idmap_get_sidbygid(GH, GID, 0, SPP, RP, ST) 1289 1290 #endif /* _KERNEL */ 1291 1292 struct mapinfo2sid { 1293 /* Yet another kernel vs. user difference. */ 1294 #ifdef _KERNEL 1295 const char *mi_dsid; /* domain SID */ 1296 #else /* _KERNEL */ 1297 char *mi_dsid; 1298 #endif /* _KERNEL */ 1299 uint32_t mi_rid; /* relative ID */ 1300 idmap_stat mi_status; 1301 }; 1302 1303 /* 1304 * Build an idmap request. Cleanup is 1305 * handled by the caller (error or not) 1306 */ 1307 static int 1308 mkrq_idmap_ux2sid( 1309 idmap_get_handle_t *idmap_gh, 1310 struct mapinfo2sid *mip, 1311 uid_t uid, /* or gid */ 1312 int req_type) 1313 { 1314 idmap_stat idms; 1315 1316 switch (req_type) { 1317 1318 case IDM_TYPE_USER: 1319 if (uid == (uid_t)-1) 1320 return (EINVAL); 1321 idms = I_getsidbyuid(idmap_gh, uid, 1322 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status); 1323 break; 1324 1325 case IDM_TYPE_GROUP: 1326 if (uid == (uid_t)-1) 1327 return (EINVAL); 1328 idms = I_getsidbygid(idmap_gh, uid, 1329 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status); 1330 break; 1331 1332 case IDM_EVERYONE: 1333 mip->mi_dsid = "S-1-1"; 1334 mip->mi_rid = 0; 1335 mip->mi_status = 0; 1336 idms = IDMAP_SUCCESS; 1337 break; 1338 1339 default: 1340 idms = IDMAP_ERR_OTHER; 1341 break; 1342 } 1343 1344 if (idms != IDMAP_SUCCESS) 1345 return (EINVAL); 1346 1347 return (0); 1348 } 1349 1350 /* 1351 * Convert a ZFS ACE to an NT ACE. 1352 * ACE type was already validated. 1353 */ 1354 static int 1355 zace2ntace(i_ntace_t **ntacep, ace_t *zacep, struct mapinfo2sid *mip) 1356 { 1357 const struct zaf2naf *znaf; 1358 uint8_t aflags; 1359 uint16_t alloc_size; 1360 uint32_t rights; 1361 i_ntace_t *ntace = NULL; 1362 i_ntsid_t *sid = NULL; 1363 int error; 1364 1365 if (mip->mi_dsid == NULL || mip->mi_status != 0) { 1366 return (EINVAL); 1367 } 1368 1369 /* 1370 * Translate ZFS ACE flags to NT ACE flags. 1371 */ 1372 aflags = 0; 1373 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++) 1374 if (zacep->a_flags & znaf->za_flag) 1375 aflags |= znaf->na_flag; 1376 1377 /* 1378 * The access rights bits are OK as-is. 1379 */ 1380 rights = zacep->a_access_mask; 1381 1382 /* 1383 * Make sure we can get the SID. 1384 * Note: allocates sid. 1385 */ 1386 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, &sid); 1387 if (error) 1388 return (error); 1389 1390 /* 1391 * Allocate the NT ACE and fill it in. 1392 */ 1393 alloc_size = sizeof (i_ntace_v2_t); 1394 if ((ntace = MALLOC(alloc_size)) == NULL) { 1395 ifree_sid(sid); 1396 return (ENOMEM); 1397 } 1398 bzero(ntace, alloc_size); 1399 1400 ntace->ace_hdr.ace_type = zacep->a_type; 1401 ntace->ace_hdr.ace_flags = aflags; 1402 ntace->ace_hdr.ace_size = alloc_size; 1403 ntace->ace_v2.ace_rights = rights; 1404 ntace->ace_v2.ace_sid = sid; 1405 1406 *ntacep = ntace; 1407 return (0); 1408 } 1409 1410 /* 1411 * Convert a ZFS-style ACL to an internal SD. 1412 * Set owner/group too if selector indicates. 1413 * Always need to pass uid+gid, either the new 1414 * (when setting them) or existing, so that any 1415 * owner@ or group@ ACEs can be translated. 1416 * 1417 * This makes two passes over the ZFS ACL. The first builds a 1418 * "batch" request for idmap with results in mapinfo, and the 1419 * second builds the NT SD using the idmap SID results. 1420 */ 1421 int 1422 smbfs_acl_zfs2sd( 1423 #ifdef _KERNEL 1424 vsecattr_t *acl_info, 1425 #else /* _KERNEL */ 1426 acl_t *acl_info, 1427 #endif /* _KERNEL */ 1428 uid_t own_uid, 1429 gid_t own_gid, 1430 uint32_t selector, 1431 i_ntsd_t **sdp) 1432 { 1433 struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL; 1434 int aclsz, error, i, mapcnt; 1435 int dacl_acecnt = 0; 1436 int sacl_acecnt = 0; 1437 int zacecnt = 0; 1438 ace_t *zacevec = NULL; 1439 ace_t *zacep; 1440 i_ntsd_t *sd = NULL; 1441 i_ntacl_t *acl = NULL; 1442 i_ntace_t **acep = NULL; 1443 #ifndef _KERNEL 1444 idmap_handle_t *idmap_h = NULL; 1445 #endif /* _KERNEL */ 1446 idmap_get_handle_t *idmap_gh = NULL; 1447 idmap_stat idms; 1448 1449 /* 1450 * First, get all the UID+GID to SID mappings. 1451 * How many? Also sanity checks. 1452 */ 1453 mapcnt = 0; 1454 if (selector & OWNER_SECURITY_INFORMATION) { 1455 if (own_uid == (uid_t)-1) 1456 return (EINVAL); 1457 mapcnt++; 1458 } 1459 if (selector & GROUP_SECURITY_INFORMATION) { 1460 if (own_gid == (gid_t)-1) 1461 return (EINVAL); 1462 mapcnt++; 1463 } 1464 if (selector & (DACL_SECURITY_INFORMATION | 1465 SACL_SECURITY_INFORMATION)) { 1466 if (acl_info == NULL) 1467 return (EINVAL); 1468 if (own_uid == (uid_t)-1) 1469 return (EINVAL); 1470 if (own_gid == (gid_t)-1) 1471 return (EINVAL); 1472 #ifdef _KERNEL 1473 if ((acl_info->vsa_mask & VSA_ACE) == 0) 1474 return (EINVAL); 1475 zacecnt = acl_info->vsa_aclcnt; 1476 zacevec = acl_info->vsa_aclentp; 1477 #else /* _KERNEL */ 1478 if (acl_info->acl_type != ACE_T || 1479 acl_info->acl_entry_size != sizeof (ace_t)) 1480 return (EINVAL); 1481 zacecnt = acl_info->acl_cnt; 1482 zacevec = acl_info->acl_aclp; 1483 #endif /* _KERNEL */ 1484 if (zacecnt == 0 || zacevec == NULL) 1485 return (EINVAL); 1486 mapcnt += zacecnt; 1487 } 1488 if (mapcnt == 0) 1489 return (EINVAL); 1490 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo)); 1491 if (mapinfo == NULL) 1492 return (ENOMEM); 1493 bzero(mapinfo, mapcnt * sizeof (*mapinfo)); 1494 /* no more returns until errout */ 1495 1496 /* 1497 * Get an imap "batch" request handle. 1498 */ 1499 #ifdef _KERNEL 1500 idmap_gh = kidmap_get_create(curproc->p_zone); 1501 #else /* _KERNEL */ 1502 idms = idmap_init(&idmap_h); 1503 if (idms != IDMAP_SUCCESS) { 1504 error = ENOTACTIVE; 1505 goto errout; 1506 } 1507 idms = idmap_get_create(idmap_h, &idmap_gh); 1508 if (idms != IDMAP_SUCCESS) { 1509 error = ENOTACTIVE; 1510 goto errout; 1511 } 1512 #endif /* _KERNEL */ 1513 1514 /* 1515 * Build our request to the idmap deamon, 1516 * getting SIDs for every Unix UID/GID. 1517 * Also count DACL and SACL ACEs here. 1518 */ 1519 mip = mapinfo; 1520 if (selector & OWNER_SECURITY_INFORMATION) { 1521 error = mkrq_idmap_ux2sid(idmap_gh, mip, 1522 own_uid, IDM_TYPE_USER); 1523 if (error) 1524 goto errout; 1525 mip++; 1526 } 1527 if (selector & GROUP_SECURITY_INFORMATION) { 1528 error = mkrq_idmap_ux2sid(idmap_gh, mip, 1529 own_gid, IDM_TYPE_GROUP); 1530 if (error) 1531 goto errout; 1532 mip++; 1533 } 1534 if (selector & (DACL_SECURITY_INFORMATION | 1535 SACL_SECURITY_INFORMATION)) { 1536 int rqtype; 1537 uid_t uid; 1538 1539 zacep = zacevec; 1540 for (i = 0; i < zacecnt; i++) { 1541 1542 switch (zacep->a_type) { 1543 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1544 case ACE_ACCESS_DENIED_ACE_TYPE: 1545 dacl_acecnt++; 1546 break; 1547 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1548 case ACE_SYSTEM_ALARM_ACE_TYPE: 1549 sacl_acecnt++; 1550 break; 1551 /* other types todo */ 1552 } 1553 1554 if (zacep->a_flags & ACE_EVERYONE) { 1555 rqtype = IDM_EVERYONE; 1556 uid = (uid_t)-1; 1557 } else if (zacep->a_flags & ACE_GROUP) { 1558 /* owning group (a_who = -1) */ 1559 rqtype = IDM_TYPE_GROUP; 1560 uid = (uid_t)own_gid; 1561 } else if (zacep->a_flags & ACE_OWNER) { 1562 /* owning user (a_who = -1) */ 1563 rqtype = IDM_TYPE_USER; 1564 uid = (uid_t)own_uid; 1565 } else if (zacep->a_flags & ACE_IDENTIFIER_GROUP) { 1566 /* regular group */ 1567 rqtype = IDM_TYPE_GROUP; 1568 uid = zacep->a_who; 1569 } else { 1570 rqtype = IDM_TYPE_USER; 1571 uid = zacep->a_who; 1572 } 1573 1574 error = mkrq_idmap_ux2sid(idmap_gh, mip, uid, rqtype); 1575 if (error) 1576 goto errout; 1577 zacep++; 1578 mip++; 1579 } 1580 } 1581 1582 idms = I_getmappings(idmap_gh); 1583 if (idms != IDMAP_SUCCESS) { 1584 /* creative error choice */ 1585 error = EIDRM; 1586 goto errout; 1587 } 1588 1589 /* 1590 * With any luck, we now have a Windows SID for 1591 * every Unix UID or GID in the NFS/ZFS ACL. 1592 * The remaining work is just format conversion, 1593 * memory allocation, etc. 1594 */ 1595 if ((sd = MALLOC(sizeof (*sd))) == NULL) { 1596 error = ENOMEM; 1597 goto errout; 1598 } 1599 bzero(sd, sizeof (*sd)); 1600 sd->sd_revision = NT_SD_REVISION; 1601 1602 mip = mapinfo; 1603 if (selector & OWNER_SECURITY_INFORMATION) { 1604 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, 1605 &sd->sd_owner); 1606 mip++; 1607 } 1608 if (selector & GROUP_SECURITY_INFORMATION) { 1609 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, 1610 &sd->sd_group); 1611 mip++; 1612 } 1613 1614 /* 1615 * If setting both DACL and SACL, we will 1616 * make two passes starting here in mapinfo. 1617 */ 1618 mip_acl = mip; 1619 1620 if (selector & DACL_SECURITY_INFORMATION) { 1621 /* 1622 * Caller wants to set the DACL. 1623 */ 1624 aclsz = I_ACL_SIZE(dacl_acecnt); 1625 if ((acl = MALLOC(aclsz)) == NULL) { 1626 error = ENOMEM; 1627 goto errout; 1628 } 1629 bzero(acl, aclsz); 1630 1631 acl->acl_revision = NT_ACL_REVISION; 1632 acl->acl_acecount = (uint16_t)dacl_acecnt; 1633 acep = &acl->acl_acevec[0]; 1634 1635 /* 1st pass - scan for DACL ACE types. */ 1636 mip = mip_acl; 1637 zacep = zacevec; 1638 for (i = 0; i < zacecnt; i++) { 1639 1640 switch (zacep->a_type) { 1641 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1642 case ACE_ACCESS_DENIED_ACE_TYPE: 1643 error = zace2ntace(acep, zacep, mip); 1644 if (error != 0) 1645 goto errout; 1646 acep++; 1647 break; 1648 1649 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1650 case ACE_SYSTEM_ALARM_ACE_TYPE: 1651 break; 1652 /* other types todo */ 1653 } 1654 zacep++; 1655 mip++; 1656 } 1657 sd->sd_dacl = acl; 1658 acl = NULL; 1659 sd->sd_flags |= SD_DACL_PRESENT; 1660 } 1661 1662 if (selector & SACL_SECURITY_INFORMATION) { 1663 /* 1664 * Caller wants to set the SACL. 1665 */ 1666 aclsz = I_ACL_SIZE(sacl_acecnt); 1667 if ((acl = MALLOC(aclsz)) == NULL) { 1668 error = ENOMEM; 1669 goto errout; 1670 } 1671 bzero(acl, aclsz); 1672 1673 acl->acl_revision = NT_ACL_REVISION; 1674 acl->acl_acecount = (uint16_t)sacl_acecnt; 1675 acep = &acl->acl_acevec[0]; 1676 1677 /* 2nd pass - scan for SACL ACE types. */ 1678 mip = mip_acl; 1679 zacep = zacevec; 1680 for (i = 0; i < zacecnt; i++) { 1681 1682 switch (zacep->a_type) { 1683 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1684 case ACE_ACCESS_DENIED_ACE_TYPE: 1685 break; 1686 1687 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1688 case ACE_SYSTEM_ALARM_ACE_TYPE: 1689 error = zace2ntace(acep, zacep, mip); 1690 if (error != 0) 1691 goto errout; 1692 acep++; 1693 break; 1694 /* other types todo */ 1695 } 1696 zacep++; 1697 mip++; 1698 } 1699 sd->sd_sacl = acl; 1700 acl = NULL; 1701 sd->sd_flags |= SD_SACL_PRESENT; 1702 } 1703 1704 *sdp = sd; 1705 error = 0; 1706 1707 errout: 1708 if (error != 0) { 1709 if (acl != NULL) 1710 ifree_acl(acl); 1711 if (sd != NULL) 1712 smbfs_acl_free_sd(sd); 1713 } 1714 if (mapinfo != NULL) 1715 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo)); 1716 #ifdef _KERNEL 1717 if (idmap_gh != NULL) 1718 kidmap_get_destroy(idmap_gh); 1719 #else /* _KERNEL */ 1720 if (idmap_gh != NULL) 1721 idmap_get_destroy(idmap_gh); 1722 if (idmap_h != NULL) 1723 (void) idmap_fini(idmap_h); 1724 #endif /* _KERNEL */ 1725 1726 return (error); 1727 } 1728