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 /*
  70  * Define FREESZ() as inline function so the compiler will not
  71  * trigger variable set but not used warning for sz in calling function.
  72  */
  73 /* ARGSUSED */
  74 static inline void
  75 FREESZ(void *p, size_t sz __unused)
  76 {
  77         free(p);
  78 }
  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 }