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