1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * ACL 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 #ifdef _KERNEL 63 #define MALLOC(size) kmem_alloc(size, KM_SLEEP) 64 #define FREESZ(p, sz) kmem_free(p, sz) 65 #else /* _KERNEL */ 66 #define MALLOC(size) malloc(size) 67 #ifndef lint 68 #define FREESZ(p, sz) free(p) 69 #else /* lint */ 70 /* ARGSUSED */ 71 static void 72 FREESZ(void *p, size_t sz) 73 { 74 free(p); 75 } 76 #endif /* lint */ 77 #endif /* _KERNEL */ 78 79 #define ERRCHK(expr) if ((error = expr) != 0) goto errout 80 81 /* 82 * Security IDentifier (SID) 83 */ 84 static void 85 ifree_sid(i_ntsid_t *sid) 86 { 87 size_t sz; 88 89 if (sid == NULL) 90 return; 91 92 sz = I_SID_SIZE(sid->sid_subauthcount); 93 FREESZ(sid, sz); 94 } 95 96 static int 97 md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp) 98 { 99 i_ntsid_t *sid = NULL; 100 uint8_t revision, subauthcount; 101 uint32_t *subauthp; 102 size_t sidsz; 103 int error, i; 104 105 if ((error = md_get_uint8(mdp, &revision)) != 0) 106 return (error); 107 if ((error = md_get_uint8(mdp, &subauthcount)) != 0) 108 return (error); 109 110 sidsz = I_SID_SIZE(subauthcount); 111 112 if ((sid = MALLOC(sidsz)) == NULL) 113 return (ENOMEM); 114 115 bzero(sid, sidsz); 116 sid->sid_revision = revision; 117 sid->sid_subauthcount = subauthcount; 118 ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM)); 119 120 subauthp = &sid->sid_subauthvec[0]; 121 for (i = 0; i < subauthcount; i++) { 122 ERRCHK(md_get_uint32le(mdp, subauthp)); 123 subauthp++; 124 } 125 126 /* Success! */ 127 *sidp = sid; 128 return (0); 129 130 errout: 131 ifree_sid(sid); 132 return (error); 133 } 134 135 static int 136 mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid) 137 { 138 uint32_t *subauthp; 139 int error, i; 140 141 if (sid == NULL) 142 return (EINVAL); 143 144 ERRCHK(mb_put_uint8(mbp, sid->sid_revision)); 145 ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount)); 146 ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM)); 147 148 subauthp = &sid->sid_subauthvec[0]; 149 for (i = 0; i < sid->sid_subauthcount; i++) { 150 ERRCHK(mb_put_uint32le(mbp, *subauthp)); 151 subauthp++; 152 } 153 154 /* Success! */ 155 return (0); 156 157 errout: 158 return (error); 159 } 160 161 162 /* 163 * Access Control Entry (ACE) 164 */ 165 static void 166 ifree_ace(i_ntace_t *ace) 167 { 168 169 if (ace == NULL) 170 return; 171 172 ifree_sid(ace->ace_sid); 173 FREESZ(ace, sizeof (*ace)); 174 } 175 176 static int 177 md_get_ace(mdchain_t *mdp, i_ntace_t **acep) 178 { 179 mdchain_t tmp_md; 180 i_ntace_t *ace = NULL; 181 uint16_t ace_len; 182 int error; 183 184 if ((ace = MALLOC(sizeof (*ace))) == NULL) 185 return (ENOMEM); 186 bzero(ace, sizeof (*ace)); 187 188 /* 189 * The ACE is realy variable length, 190 * with format determined by the type. 191 * XXX: This only decodes types 0-7 192 * 193 * There may also be padding after it, so 194 * decode the using a copy of the mdchain, 195 * and then consume the specified length. 196 */ 197 tmp_md = *mdp; 198 199 /* Fixed-size header */ 200 ERRCHK(md_get_uint8(&tmp_md, &ace->ace_type)); 201 ERRCHK(md_get_uint8(&tmp_md, &ace->ace_flags)); 202 ERRCHK(md_get_uint16le(&tmp_md, &ace_len)); 203 204 /* Variable-size body */ 205 ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_rights)); 206 ERRCHK(md_get_sid(&tmp_md, &ace->ace_sid)); 207 208 /* Now actually consume ace_len */ 209 ERRCHK(md_get_mem(mdp, NULL, ace_len, MB_MSYSTEM)); 210 211 /* Success! */ 212 *acep = ace; 213 return (0); 214 215 errout: 216 ifree_ace(ace); 217 return (error); 218 } 219 220 static int 221 mb_put_ace(mbchain_t *mbp, i_ntace_t *ace) 222 { 223 int cnt0, error; 224 uint16_t ace_len, *ace_len_p; 225 226 if (ace == NULL) 227 return (EINVAL); 228 229 cnt0 = mbp->mb_count; 230 231 ERRCHK(mb_put_uint8(mbp, ace->ace_type)); 232 ERRCHK(mb_put_uint8(mbp, ace->ace_flags)); 233 ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p)); 234 if (ace_len_p == NULL) { 235 error = ENOMEM; 236 goto errout; 237 } 238 ERRCHK(mb_put_uint32le(mbp, ace->ace_rights)); 239 240 ERRCHK(mb_put_sid(mbp, ace->ace_sid)); 241 242 ace_len = mbp->mb_count - cnt0; 243 *ace_len_p = htoles(ace_len); 244 245 /* Success! */ 246 return (0); 247 248 errout: 249 return (error); 250 } 251 252 253 /* 254 * Access Control List (ACL) 255 */ 256 257 /* Not an OTW structure, so size can be at our convenience. */ 258 #define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *)) 259 260 static void 261 ifree_acl(i_ntacl_t *acl) 262 { 263 i_ntace_t **acep; 264 size_t sz; 265 int i; 266 267 if (acl == NULL) 268 return; 269 270 acep = &acl->acl_acevec[0]; 271 for (i = 0; i < acl->acl_acecount; i++) { 272 ifree_ace(*acep); 273 acep++; 274 } 275 sz = I_ACL_SIZE(acl->acl_acecount); 276 FREESZ(acl, sz); 277 } 278 279 static int 280 md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp) 281 { 282 i_ntacl_t *acl = NULL; 283 i_ntace_t **acep; 284 uint8_t revision; 285 uint16_t acl_len, acecount; 286 size_t aclsz; 287 int i, error; 288 289 if ((error = md_get_uint8(mdp, &revision)) != 0) 290 return (error); 291 if ((error = md_get_uint8(mdp, NULL)) != 0) 292 return (error); 293 if ((error = md_get_uint16le(mdp, &acl_len)) != 0) 294 return (error); 295 if ((error = md_get_uint16le(mdp, &acecount)) != 0) 296 return (error); 297 if ((error = md_get_uint16le(mdp, NULL)) != 0) 298 return (error); 299 300 aclsz = I_ACL_SIZE(acecount); 301 if ((acl = MALLOC(aclsz)) == NULL) 302 return (ENOMEM); 303 bzero(acl, aclsz); 304 acl->acl_revision = revision; 305 acl->acl_acecount = acecount; 306 307 acep = &acl->acl_acevec[0]; 308 for (i = 0; i < acl->acl_acecount; i++) { 309 ERRCHK(md_get_ace(mdp, acep)); 310 acep++; 311 } 312 /* 313 * There may be more data here, but 314 * the caller takes care of that. 315 */ 316 317 /* Success! */ 318 *aclp = acl; 319 return (0); 320 321 errout: 322 ifree_acl(acl); 323 return (error); 324 } 325 326 static int 327 mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl) 328 { 329 i_ntace_t **acep; 330 uint16_t acl_len, *acl_len_p; 331 int i, cnt0, error; 332 333 cnt0 = mbp->mb_count; 334 335 ERRCHK(mb_put_uint8(mbp, acl->acl_revision)); 336 ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */ 337 acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p)); 338 if (acl_len_p == NULL) { 339 error = ENOMEM; 340 goto errout; 341 } 342 ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount)); 343 ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */ 344 345 acep = &acl->acl_acevec[0]; 346 for (i = 0; i < acl->acl_acecount; i++) { 347 ERRCHK(mb_put_ace(mbp, *acep)); 348 acep++; 349 } 350 351 /* Fill in acl_len_p */ 352 acl_len = mbp->mb_count - cnt0; 353 *acl_len_p = htoles(acl_len); 354 355 /* Success! */ 356 return (0); 357 358 errout: 359 return (error); 360 } 361 362 363 /* 364 * Security Descriptor 365 */ 366 void 367 smbfs_acl_free_sd(i_ntsd_t *sd) 368 { 369 370 if (sd == NULL) 371 return; 372 373 ifree_sid(sd->sd_owner); 374 ifree_sid(sd->sd_group); 375 ifree_acl(sd->sd_sacl); 376 ifree_acl(sd->sd_dacl); 377 378 FREESZ(sd, sizeof (*sd)); 379 } 380 381 /* 382 * Import a raw SD (mb chain) into "internal" form. 383 * (like "absolute" form per. NT docs) 384 * Returns allocated data in sdp 385 * 386 * Note: does NOT consume all the mdp data, so the 387 * caller has to take care of that if necessary. 388 */ 389 int 390 md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp) 391 { 392 i_ntsd_t *sd = NULL; 393 mdchain_t top_md, tmp_md; 394 uint32_t owneroff, groupoff, sacloff, dacloff; 395 int error; 396 397 if ((sd = MALLOC(sizeof (*sd))) == NULL) 398 return (ENOMEM); 399 bzero(sd, sizeof (*sd)); 400 401 /* 402 * Offsets below are relative to this point, 403 * so save the mdp state for use below. 404 */ 405 top_md = *mdp; 406 407 ERRCHK(md_get_uint8(mdp, &sd->sd_revision)); 408 ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl)); 409 ERRCHK(md_get_uint16le(mdp, &sd->sd_flags)); 410 ERRCHK(md_get_uint32le(mdp, &owneroff)); 411 ERRCHK(md_get_uint32le(mdp, &groupoff)); 412 ERRCHK(md_get_uint32le(mdp, &sacloff)); 413 ERRCHK(md_get_uint32le(mdp, &dacloff)); 414 415 /* 416 * For each section make a temporary copy of the 417 * top_md state, advance to the given offset, and 418 * pass that to the lower md_get_xxx functions. 419 * These could be marshalled in any order, but 420 * are normally found in the order shown here. 421 */ 422 if (sacloff) { 423 tmp_md = top_md; 424 md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM); 425 ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl)); 426 } 427 if (dacloff) { 428 tmp_md = top_md; 429 md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM); 430 ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl)); 431 } 432 if (owneroff) { 433 tmp_md = top_md; 434 md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM); 435 ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner)); 436 } 437 if (groupoff) { 438 tmp_md = top_md; 439 md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM); 440 ERRCHK(md_get_sid(&tmp_md, &sd->sd_group)); 441 } 442 443 /* Success! */ 444 *sdp = sd; 445 return (0); 446 447 errout: 448 smbfs_acl_free_sd(sd); 449 return (error); 450 } 451 452 /* 453 * Export an "internal" SD into an raw SD (mb chain). 454 * (a.k.a "self-relative" form per. NT docs) 455 * Returns allocated mbchain in mbp. 456 */ 457 int 458 mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd) 459 { 460 uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp; 461 uint32_t owneroff, groupoff, sacloff, dacloff; 462 int cnt0, error; 463 464 cnt0 = mbp->mb_count; 465 owneroff = groupoff = sacloff = dacloff = 0; 466 467 ERRCHK(mb_put_uint8(mbp, sd->sd_revision)); 468 ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl)); 469 ERRCHK(mb_put_uint16le(mbp, sd->sd_flags)); 470 471 owneroffp = mb_reserve(mbp, sizeof (*owneroffp)); 472 groupoffp = mb_reserve(mbp, sizeof (*groupoffp)); 473 sacloffp = mb_reserve(mbp, sizeof (*sacloffp)); 474 dacloffp = mb_reserve(mbp, sizeof (*dacloffp)); 475 if (owneroffp == NULL || groupoffp == NULL || 476 sacloffp == NULL || dacloffp == NULL) { 477 error = ENOMEM; 478 goto errout; 479 } 480 481 /* 482 * These could be marshalled in any order, but 483 * are normally found in the order shown here. 484 */ 485 if (sd->sd_sacl) { 486 sacloff = mbp->mb_count - cnt0; 487 ERRCHK(mb_put_acl(mbp, sd->sd_sacl)); 488 } 489 if (sd->sd_dacl) { 490 dacloff = mbp->mb_count - cnt0; 491 ERRCHK(mb_put_acl(mbp, sd->sd_dacl)); 492 } 493 if (sd->sd_owner) { 494 owneroff = mbp->mb_count - cnt0; 495 ERRCHK(mb_put_sid(mbp, sd->sd_owner)); 496 } 497 if (sd->sd_group) { 498 groupoff = mbp->mb_count - cnt0; 499 ERRCHK(mb_put_sid(mbp, sd->sd_group)); 500 } 501 502 /* Fill in the offsets */ 503 *owneroffp = htolel(owneroff); 504 *groupoffp = htolel(groupoff); 505 *sacloffp = htolel(sacloff); 506 *dacloffp = htolel(dacloff); 507 508 /* Success! */ 509 return (0); 510 511 errout: 512 return (error); 513 } 514 515 516 /* 517 * Helper functions for conversion between ZFS-style ACLs 518 * and Windows Security Descriptors. 519 */ 520 521 522 /* 523 * Convert an NT SID to a string. Optionally return the 524 * last sub-authority (or "relative ID" -- RID) in *ridp 525 * and truncate the output string after the domain part. 526 * If ridp==NULL, the output string is the whole SID, 527 * including both the domain and RID. 528 * 529 * Return length written, or -1 on error. 530 */ 531 int 532 smbfs_sid2str(i_ntsid_t *sid, 533 char *obuf, size_t osz, uint32_t *ridp) 534 { 535 char *s = obuf; 536 uint64_t auth = 0; 537 uint_t i, n; 538 uint32_t subs, *ip; 539 540 n = snprintf(s, osz, "S-%u", sid->sid_revision); 541 if (n > osz) 542 return (-1); 543 s += n; osz -= n; 544 545 for (i = 0; i < 6; i++) 546 auth = (auth << 8) | sid->sid_authority[i]; 547 n = snprintf(s, osz, "-%llu", (u_longlong_t)auth); 548 if (n > osz) 549 return (-1); 550 s += n; osz -= n; 551 552 subs = sid->sid_subauthcount; 553 if (subs < 1 || subs > 15) 554 return (-1); 555 if (ridp) 556 subs--; 557 558 ip = &sid->sid_subauthvec[0]; 559 for (; subs; subs--, ip++) { 560 n = snprintf(s, osz, "-%u", *ip); 561 if (n > osz) 562 return (-1); 563 s += n; osz -= n; 564 } 565 if (ridp) 566 *ridp = *ip; 567 568 /* LINTED E_PTRDIFF_OVERFLOW */ 569 return (s - obuf); 570 } 571 572 /* 573 * Our interface to the idmap service. 574 * 575 * The idmap API is _almost_ the same between 576 * kernel and user-level. But not quite... 577 * Hope this improves readability below. 578 */ 579 #ifdef _KERNEL 580 581 #define I_GetPidBySid(GH, SPP, RID, PIDP, ISUP, SP) \ 582 kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) 583 #define I_GetMappings kidmap_get_mappings 584 585 #else /* _KERNEL */ 586 587 #define I_GetPidBySid(GH, SPP, RID, PIDP, ISUP, SP) \ 588 idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP) 589 #define I_GetMappings idmap_get_mappings 590 591 #endif /* _KERNEL */ 592 593 struct mapinfo { 594 uid_t mi_uid; /* or gid */ 595 int mi_isuser; 596 idmap_stat mi_status; 597 }; 598 599 /* 600 * A special value for mi_isuser (above) to indicate 601 * that the SID is the well-known "Everyone" (S-1-1-0). 602 * The idmap library only uses -1, 0, 1, so this value 603 * is arbitrary but must not overlap w/ idmap values. 604 * XXX: Could use a way for idmap to tell us when 605 * it recognizes this well-known SID. 606 */ 607 #define IS_WKSID_EVERYONE 11 608 609 /* 610 * Build an idmap request. Cleanup is 611 * handled by the caller (error or not) 612 */ 613 static int 614 mkrq_idmap_sid2ux( 615 idmap_get_handle_t *idmap_gh, 616 i_ntsid_t *sid, 617 struct mapinfo *mip) 618 { 619 char sid_prefix[256]; 620 uint32_t rid; 621 idmap_stat idms; 622 623 if (smbfs_sid2str(sid, sid_prefix, sizeof (sid_prefix), &rid) < 0) 624 return (EINVAL); 625 626 /* 627 * Give the "Everyone" group special treatment. 628 */ 629 if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) { 630 /* This is "Everyone" */ 631 mip->mi_uid = (uid_t)-1; 632 mip->mi_isuser = IS_WKSID_EVERYONE; 633 mip->mi_status = 0; 634 return (0); 635 } 636 637 idms = I_GetPidBySid(idmap_gh, sid_prefix, rid, 638 &mip->mi_uid, &mip->mi_isuser, &mip->mi_status); 639 if (idms != IDMAP_SUCCESS) 640 return (EINVAL); 641 642 return (0); 643 } 644 645 static void 646 ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo *mip) 647 { 648 uint32_t zamask; 649 uint16_t zflags, ntflags; 650 uint8_t zatype = ntace->ace_type; 651 652 /* 653 * Translate NT ACE flags to ZFS ACE flags. 654 * The low four bits are the same, but not 655 * others: INHERITED_ACE_FLAG, etc. 656 */ 657 ntflags = ntace->ace_flags; 658 zflags = 0; 659 660 if (ntflags & OBJECT_INHERIT_ACE_FLAG) 661 zflags |= ACE_FILE_INHERIT_ACE; 662 if (ntflags & CONTAINER_INHERIT_ACE_FLAG) 663 zflags |= ACE_DIRECTORY_INHERIT_ACE; 664 if (ntflags & NO_PROPAGATE_INHERIT_ACE_FLAG) 665 zflags |= ACE_NO_PROPAGATE_INHERIT_ACE; 666 if (ntflags & INHERIT_ONLY_ACE_FLAG) 667 zflags |= ACE_INHERIT_ONLY_ACE; 668 if (ntflags & INHERITED_ACE_FLAG) 669 zflags |= ACE_INHERITED_ACE; 670 671 if (ntflags & SUCCESSFUL_ACCESS_ACE_FLAG) 672 zflags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 673 if (ntflags & FAILED_ACCESS_ACE_FLAG) 674 zflags |= ACE_FAILED_ACCESS_ACE_FLAG; 675 676 /* 677 * Add the "ID type" flags to the ZFS ace flags. 678 * Would be nice if the idmap header defined some 679 * manifest constants for these "isuser" values. 680 */ 681 switch (mip->mi_isuser) { 682 case IS_WKSID_EVERYONE: 683 zflags |= ACE_EVERYONE; 684 break; 685 case 0: /* it's a GID */ 686 zflags |= ACE_IDENTIFIER_GROUP; 687 break; 688 default: 689 case 1: /* it's a UID */ 690 break; 691 } 692 693 /* 694 * The access mask bits are the same, but 695 * mask off any bits we don't expect. 696 * Should not see any GENERIC_xxx flags, 697 * as those are only valid in requested 698 * access masks, not ACLs. But if we do, 699 * get those, silently clear them here. 700 */ 701 zamask = ntace->ace_rights & ACE_ALL_PERMS; 702 703 /* 704 * Verify that it's a known ACE type. 705 * Only handle the types that appear in 706 * V2, V3, V4 ACLs for now. Avoid failing 707 * the whole conversion if we get unknown 708 * ace types, but convert them to something 709 * that will have no effect on access. 710 */ 711 if (zatype > SYSTEM_ALARM_OBJECT_ACE_TYPE) { 712 zatype = ACCESS_ALLOWED_ACE_TYPE; 713 zamask = 0; /* harmless */ 714 } 715 716 /* 717 * Fill in the ZFS-style ACE 718 */ 719 zacep->a_who = mip->mi_uid; /* from ace_sid */ 720 zacep->a_access_mask = zamask; 721 zacep->a_flags = zflags; 722 zacep->a_type = zatype; 723 } 724 725 /* 726 * Convert an internal SD to a ZFS-style ACL. 727 * Note optional args: vsa/acl, uidp, gidp. 728 */ 729 int 730 smbfs_acl_sd2zfs( 731 i_ntsd_t *sd, 732 #ifdef _KERNEL 733 vsecattr_t *acl_info, 734 #else /* _KERNEL */ 735 acl_t *acl_info, 736 #endif /* _KERNEL */ 737 uid_t *uidp, gid_t *gidp) 738 { 739 struct mapinfo *mip, *mapinfo = NULL; 740 int error, i, mapcnt, zacecnt, zacl_size; 741 ace_t *zacep; 742 i_ntacl_t *ntacl; 743 i_ntace_t **ntacep; 744 #ifndef _KERNEL 745 idmap_handle_t *idmap_h = NULL; 746 #endif /* _KERNEL */ 747 idmap_get_handle_t *idmap_gh = NULL; 748 idmap_stat idms; 749 750 /* 751 * sanity checks 752 */ 753 #ifndef _KERNEL 754 if (acl_info) { 755 if (acl_info->acl_type != ACE_T || 756 acl_info->acl_aclp != NULL || 757 acl_info->acl_entry_size != sizeof (ace_t)) 758 return (EINVAL); 759 } 760 #endif /* _KERNEL */ 761 762 /* 763 * First, get all the SID mappings. 764 * How many? 765 */ 766 mapcnt = 0; 767 if (sd->sd_owner) 768 mapcnt++; 769 if (sd->sd_group) 770 mapcnt++; 771 if (sd->sd_sacl) 772 mapcnt += sd->sd_sacl->acl_acecount; 773 if (sd->sd_dacl) 774 mapcnt += sd->sd_dacl->acl_acecount; 775 if (mapcnt == 0) 776 return (EINVAL); 777 778 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo)); 779 if (mapinfo == NULL) { 780 error = ENOMEM; 781 goto errout; 782 } 783 bzero(mapinfo, mapcnt * sizeof (*mapinfo)); 784 785 786 /* 787 * Build our request to the idmap deamon. 788 */ 789 #ifdef _KERNEL 790 idmap_gh = kidmap_get_create(curproc->p_zone); 791 #else /* _KERNEL */ 792 idms = idmap_init(&idmap_h); 793 if (idms != IDMAP_SUCCESS) { 794 error = ENOTACTIVE; 795 goto errout; 796 } 797 idms = idmap_get_create(idmap_h, &idmap_gh); 798 if (idms != IDMAP_SUCCESS) { 799 error = ENOTACTIVE; 800 goto errout; 801 } 802 #endif /* _KERNEL */ 803 804 mip = mapinfo; 805 if (sd->sd_owner) { 806 error = mkrq_idmap_sid2ux( 807 idmap_gh, sd->sd_owner, mip); 808 if (error) 809 goto errout; 810 mip++; 811 } 812 if (sd->sd_group) { 813 error = mkrq_idmap_sid2ux( 814 idmap_gh, sd->sd_group, mip); 815 if (error) 816 goto errout; 817 mip++; 818 } 819 if (sd->sd_sacl) { 820 ntacl = sd->sd_sacl; 821 ntacep = &ntacl->acl_acevec[0]; 822 for (i = 0; i < ntacl->acl_acecount; i++) { 823 error = mkrq_idmap_sid2ux( 824 idmap_gh, (*ntacep)->ace_sid, mip); 825 if (error) 826 goto errout; 827 ntacep++; 828 mip++; 829 } 830 } 831 if (sd->sd_dacl) { 832 ntacl = sd->sd_dacl; 833 ntacep = &ntacl->acl_acevec[0]; 834 for (i = 0; i < ntacl->acl_acecount; i++) { 835 error = mkrq_idmap_sid2ux( 836 idmap_gh, (*ntacep)->ace_sid, mip); 837 if (error) 838 goto errout; 839 ntacep++; 840 mip++; 841 } 842 } 843 844 idms = I_GetMappings(idmap_gh); 845 if (idms != IDMAP_SUCCESS) { 846 /* creative error choice */ 847 error = EIDRM; 848 goto errout; 849 } 850 851 /* 852 * With any luck, we now have Unix user/group IDs 853 * for every Windows SID in the security descriptor. 854 * The remaining work is just format conversion. 855 */ 856 mip = mapinfo; 857 if (sd->sd_owner) { 858 if (uidp) { 859 if (mip->mi_isuser == 1) 860 *uidp = mip->mi_uid; 861 else 862 *uidp = (uid_t)-1; 863 } 864 mip++; 865 } else { 866 if (uidp) 867 *uidp = (uid_t)-1; 868 } 869 if (sd->sd_group) { 870 if (gidp) { 871 if (mip->mi_isuser == 0) 872 *gidp = (gid_t)mip->mi_uid; 873 else 874 *gidp = (gid_t)-1; 875 } 876 mip++; 877 } else { 878 if (gidp) 879 *gidp = (gid_t)-1; 880 } 881 882 if (acl_info == NULL) { 883 /* Caller only wanted uid/gid */ 884 goto ok_out; 885 } 886 887 /* 888 * Build the ZFS-style ACL 889 */ 890 zacecnt = 0; 891 if (sd->sd_sacl) 892 zacecnt += sd->sd_sacl->acl_acecount; 893 if (sd->sd_dacl) 894 zacecnt += sd->sd_dacl->acl_acecount; 895 zacl_size = zacecnt * sizeof (ace_t); 896 zacep = MALLOC(zacl_size); 897 #ifdef _KERNEL 898 acl_info->vsa_aclentp = zacep; 899 acl_info->vsa_aclentsz = zacl_size; 900 #else /* _KERNEL */ 901 if (zacep == NULL) { 902 error = ENOMEM; 903 goto errout; 904 } 905 acl_info->acl_cnt = zacecnt; 906 acl_info->acl_aclp = zacep; 907 #endif /* _KERNEL */ 908 909 if (sd->sd_sacl) { 910 ntacl = sd->sd_sacl; 911 ntacep = &ntacl->acl_acevec[0]; 912 for (i = 0; i < ntacl->acl_acecount; i++) { 913 ntace2zace(zacep, *ntacep, mip); 914 zacep++; 915 ntacep++; 916 mip++; 917 } 918 } 919 if (sd->sd_dacl) { 920 ntacl = sd->sd_dacl; 921 ntacep = &ntacl->acl_acevec[0]; 922 for (i = 0; i < ntacl->acl_acecount; i++) { 923 ntace2zace(zacep, *ntacep, mip); 924 zacep++; 925 ntacep++; 926 mip++; 927 } 928 } 929 930 ok_out: 931 error = 0; 932 933 errout: 934 if (mapinfo) 935 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo)); 936 937 return (error); 938 } 939 940 941 /* 942 * Convert an internal SD to a ZFS-style ACL. 943 * Include owner/group too if uid/gid != -1. 944 * Note optional arg: vsa/acl 945 */ 946 /*ARGSUSED*/ 947 int smbfs_acl_zfs2sd( 948 #ifdef _KERNEL 949 vsecattr_t *vsa, 950 #else /* _KERNEL */ 951 acl_t *acl, 952 #endif /* _KERNEL */ 953 uid_t uid, gid_t gid, 954 i_ntsd_t **sdp) 955 { 956 /* XXX - todo */ 957 return (ENOSYS); 958 } 959