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 */
  47 
  48 #include <stdio.h>
  49 #include <stdlib.h>
  50 #include <strings.h>
  51 
  52 #endif  /* _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 }