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