8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / common / smbclnt / smbfs_ntacl.c
blob6780d891ee514e01b6799f8cbd33e80772b18ccb
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
27 * ACL conversion support for smbfs
28 * (To/from NT/ZFS-style ACLs.)
31 #include <sys/types.h>
32 #include <sys/errno.h>
33 #include <sys/acl.h>
34 #include <sys/byteorder.h>
36 #ifdef _KERNEL
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>
45 #include <sys/kidmap.h>
47 #else /* _KERNEL */
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <strings.h>
53 #include <idmap.h>
55 #endif /* _KERNEL */
57 #include <netsmb/mchain.h>
58 #include <netsmb/smb.h>
59 #include "smbfs_ntacl.h"
61 #define NT_SD_REVISION 1
62 #define NT_ACL_REVISION 2
64 #ifdef _KERNEL
65 #define MALLOC(size) kmem_alloc(size, KM_SLEEP)
66 #define FREESZ(p, sz) kmem_free(p, sz)
67 #else /* _KERNEL */
68 #define MALLOC(size) malloc(size)
69 #ifndef lint
70 #define FREESZ(p, sz) free(p)
71 #else /* lint */
72 /* ARGSUSED */
73 static void
74 FREESZ(void *p, size_t sz)
76 free(p);
78 #endif /* lint */
79 #endif /* _KERNEL */
81 #define ERRCHK(expr) if ((error = expr) != 0) goto errout
84 * Security IDentifier (SID)
86 static void
87 ifree_sid(i_ntsid_t *sid)
89 size_t sz;
91 if (sid == NULL)
92 return;
94 sz = I_SID_SIZE(sid->sid_subauthcount);
95 FREESZ(sid, sz);
98 static int
99 md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp)
101 i_ntsid_t *sid = NULL;
102 uint8_t revision, subauthcount;
103 uint32_t *subauthp;
104 size_t sidsz;
105 int error, i;
107 if ((error = md_get_uint8(mdp, &revision)) != 0)
108 return (error);
109 if ((error = md_get_uint8(mdp, &subauthcount)) != 0)
110 return (error);
112 sidsz = I_SID_SIZE(subauthcount);
114 if ((sid = MALLOC(sidsz)) == NULL)
115 return (ENOMEM);
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));
122 subauthp = &sid->sid_subauthvec[0];
123 for (i = 0; i < subauthcount; i++) {
124 ERRCHK(md_get_uint32le(mdp, subauthp));
125 subauthp++;
128 /* Success! */
129 *sidp = sid;
130 return (0);
132 errout:
133 ifree_sid(sid);
134 return (error);
137 static int
138 mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid)
140 uint32_t *subauthp;
141 int error, i;
143 if (sid == NULL)
144 return (EINVAL);
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));
150 subauthp = &sid->sid_subauthvec[0];
151 for (i = 0; i < sid->sid_subauthcount; i++) {
152 ERRCHK(mb_put_uint32le(mbp, *subauthp));
153 subauthp++;
156 /* Success! */
157 return (0);
159 errout:
160 return (error);
165 * Access Control Entry (ACE)
167 static void
168 ifree_ace(i_ntace_t *ace)
171 if (ace == NULL)
172 return;
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;
188 static int
189 md_get_ace(mdchain_t *mdp, i_ntace_t **acep)
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;
198 * The ACE is realy variable length,
199 * with format determined by the type.
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.
205 tmp_md = *mdp;
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));
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;
230 /* other types todo */
231 default:
232 error = EIO;
233 goto errout;
236 /* Now actually consume ace_hdr.ace_size */
237 ERRCHK(md_get_mem(mdp, NULL, ace_hdr.ace_size, MB_MSYSTEM));
239 /* Success! */
240 *acep = ace;
241 return (0);
243 errout:
244 ifree_ace(ace);
245 return (error);
248 static int
249 mb_put_ace(mbchain_t *mbp, i_ntace_t *ace)
251 int cnt0, error;
252 uint16_t ace_len, *ace_len_p;
254 if (ace == NULL)
255 return (EINVAL);
257 cnt0 = mbp->mb_count;
260 * Put the (fixed-size) ACE header
261 * Will fill in the length later.
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;
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;
281 /* other types todo */
282 default:
283 error = EIO;
284 goto errout;
287 /* Fill in the (OtW) ACE length. */
288 ace_len = mbp->mb_count - cnt0;
289 *ace_len_p = htoles(ace_len);
291 /* Success! */
292 return (0);
294 errout:
295 return (error);
300 * Access Control List (ACL)
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 *))
306 static void
307 ifree_acl(i_ntacl_t *acl)
309 i_ntace_t **acep;
310 size_t sz;
311 int i;
313 if (acl == NULL)
314 return;
316 acep = &acl->acl_acevec[0];
317 for (i = 0; i < acl->acl_acecount; i++) {
318 ifree_ace(*acep);
319 acep++;
321 sz = I_ACL_SIZE(acl->acl_acecount);
322 FREESZ(acl, sz);
325 static int
326 md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp)
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;
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);
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;
353 acep = &acl->acl_acevec[0];
354 for (i = 0; i < acl->acl_acecount; i++) {
355 ERRCHK(md_get_ace(mdp, acep));
356 acep++;
359 * There may be more data here, but
360 * the caller takes care of that.
363 /* Success! */
364 *aclp = acl;
365 return (0);
367 errout:
368 ifree_acl(acl);
369 return (error);
372 static int
373 mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl)
375 i_ntace_t **acep;
376 uint16_t acl_len, *acl_len_p;
377 int i, cnt0, error;
379 cnt0 = mbp->mb_count;
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;
388 ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
389 ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
391 acep = &acl->acl_acevec[0];
392 for (i = 0; i < acl->acl_acecount; i++) {
393 ERRCHK(mb_put_ace(mbp, *acep));
394 acep++;
397 /* Fill in acl_len_p */
398 acl_len = mbp->mb_count - cnt0;
399 *acl_len_p = htoles(acl_len);
401 /* Success! */
402 return (0);
404 errout:
405 return (error);
410 * Security Descriptor
412 void
413 smbfs_acl_free_sd(i_ntsd_t *sd)
416 if (sd == NULL)
417 return;
419 ifree_sid(sd->sd_owner);
420 ifree_sid(sd->sd_group);
421 ifree_acl(sd->sd_sacl);
422 ifree_acl(sd->sd_dacl);
424 FREESZ(sd, sizeof (*sd));
428 * Import a raw SD (mb chain) into "internal" form.
429 * (like "absolute" form per. NT docs)
430 * Returns allocated data in sdp
432 * Note: does NOT consume all the mdp data, so the
433 * caller has to take care of that if necessary.
436 md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp)
438 i_ntsd_t *sd = NULL;
439 mdchain_t top_md, tmp_md;
440 uint32_t owneroff, groupoff, sacloff, dacloff;
441 int error;
443 if ((sd = MALLOC(sizeof (*sd))) == NULL)
444 return (ENOMEM);
445 bzero(sd, sizeof (*sd));
448 * Offsets below are relative to this point,
449 * so save the mdp state for use below.
451 top_md = *mdp;
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));
462 * The SD is "self-relative" on the wire,
463 * but not after this decodes it.
465 sd->sd_flags &= ~SD_SELF_RELATIVE;
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.
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));
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));
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));
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));
495 /* Success! */
496 *sdp = sd;
497 return (0);
499 errout:
500 smbfs_acl_free_sd(sd);
501 return (error);
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.
510 mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd)
512 uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
513 uint32_t owneroff, groupoff, sacloff, dacloff;
514 uint16_t flags;
515 int cnt0, error;
517 cnt0 = mbp->mb_count;
518 owneroff = groupoff = sacloff = dacloff = 0;
520 /* The SD is "self-relative" on the wire. */
521 flags = sd->sd_flags | SD_SELF_RELATIVE;
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));
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;
538 * These could be marshalled in any order, but
539 * are normally found in the order shown here.
541 if (sd->sd_sacl) {
542 sacloff = mbp->mb_count - cnt0;
543 ERRCHK(mb_put_acl(mbp, sd->sd_sacl));
545 if (sd->sd_dacl) {
546 dacloff = mbp->mb_count - cnt0;
547 ERRCHK(mb_put_acl(mbp, sd->sd_dacl));
549 if (sd->sd_owner) {
550 owneroff = mbp->mb_count - cnt0;
551 ERRCHK(mb_put_sid(mbp, sd->sd_owner));
553 if (sd->sd_group) {
554 groupoff = mbp->mb_count - cnt0;
555 ERRCHK(mb_put_sid(mbp, sd->sd_group));
558 /* Fill in the offsets */
559 *owneroffp = htolel(owneroff);
560 *groupoffp = htolel(groupoff);
561 *sacloffp = htolel(sacloff);
562 *dacloffp = htolel(dacloff);
564 /* Success! */
565 return (0);
567 errout:
568 return (error);
572 * ================================================================
573 * Support for ACL fetch, including conversions
574 * from Windows ACLs to NFSv4-style ACLs.
575 * ================================================================
578 #define GENERIC_RIGHTS_MASK \
579 (GENERIC_RIGHT_READ_ACCESS | GENERIC_RIGHT_WRITE_ACCESS |\
580 GENERIC_RIGHT_EXECUTE_ACCESS | GENERIC_RIGHT_ALL_ACCESS)
583 * Table for converting NT GENERIC_RIGHT_... to specific rights
584 * appropriate for objects of type file.
586 struct gen2fsr {
587 uint32_t gf_generic;
588 uint32_t gf_specific;
590 static const struct gen2fsr
591 smbfs_gen2fsr[] = {
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 },
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 },
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 },
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 }
625 * Table for translating ZFS ACE flags to NT ACE flags.
626 * The low four bits are the same, but not others.
628 struct zaf2naf {
629 uint16_t za_flag;
630 uint8_t na_flag;
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 }
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.
651 * Return length written, or -1 on error.
654 smbfs_sid2str(i_ntsid_t *sid,
655 char *obuf, size_t osz, uint32_t *ridp)
657 char *s = obuf;
658 uint64_t auth = 0;
659 uint_t i, n;
660 uint32_t subs, *ip;
662 n = snprintf(s, osz, "S-%u", sid->sid_revision);
663 if (n > osz)
664 return (-1);
665 s += n; osz -= n;
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;
674 subs = sid->sid_subauthcount;
675 if (subs < 1 || subs > 15)
676 return (-1);
677 if (ridp)
678 subs--;
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;
687 if (ridp)
688 *ridp = *ip;
690 /* LINTED E_PTRDIFF_OVERFLOW */
691 return (s - obuf);
695 * Our interface to the idmap service.
697 * The idmap API is _almost_ the same between
698 * kernel and user-level. But not quite...
699 * Hope this improves readability below.
701 #ifdef _KERNEL
703 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
704 kidmap_batch_getuidbysid(GH, SPP, RID, UIDP, SP)
706 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
707 kidmap_batch_getgidbysid(GH, SPP, RID, GIDP, SP)
709 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
710 kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP)
712 #define I_getmappings kidmap_get_mappings
714 #else /* _KERNEL */
716 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
717 idmap_get_uidbysid(GH, SPP, RID, 0, UIDP, SP)
719 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
720 idmap_get_gidbysid(GH, SPP, RID, 0, GIDP, SP)
722 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
723 idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP)
725 #define I_getmappings idmap_get_mappings
727 #endif /* _KERNEL */
731 * The idmap request types, chosen so they also
732 * match the values returned in mi_isuser.
734 #define IDM_TYPE_ANY -1
735 #define IDM_TYPE_GROUP 0
736 #define IDM_TYPE_USER 1
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.
746 #define IDM_EVERYONE 11
748 struct mapinfo2uid {
749 uid_t mi_uid; /* or gid, or pid */
750 int mi_isuser; /* IDM_TYPE */
751 idmap_stat mi_status;
755 * Build an idmap request. Cleanup is
756 * handled by the caller (error or not)
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)
765 char strbuf[256];
766 char *sid_prefix;
767 uint32_t rid;
768 idmap_stat idms;
770 if (smbfs_sid2str(sid, strbuf, sizeof (strbuf), &rid) < 0)
771 return (EINVAL);
772 sid_prefix = strbuf;
775 * Give the "Everyone" group special treatment.
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);
785 switch (req_type) {
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;
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;
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;
804 default:
805 idms = IDMAP_ERR_OTHER;
806 break;
809 if (idms != IDMAP_SUCCESS)
810 return (EINVAL);
812 return (0);
816 * Convert an NT ACE to a ZFS ACE.
817 * ACE type was already validated.
819 static void
820 ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo2uid *mip)
822 const struct zaf2naf *znaf;
823 uid_t zwho;
824 uint32_t zamask;
825 uint16_t zflags;
828 * Set the "ID type" flags in the ZFS ace flags.
830 zflags = 0;
831 switch (mip->mi_isuser) {
832 case IDM_EVERYONE:
833 zflags = ACE_EVERYONE;
834 zwho = (uid_t)-1;
835 break;
837 case IDM_TYPE_GROUP: /* it's a GID */
838 zflags = ACE_IDENTIFIER_GROUP;
839 zwho = mip->mi_uid;
840 break;
842 default:
843 case IDM_TYPE_USER: /* it's a UID */
844 zflags = 0;
845 zwho = mip->mi_uid;
846 break;
850 * Translate NT ACE flags to ZFS ACE flags.
852 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
853 if (ntace->ace_hdr.ace_flags & znaf->na_flag)
854 zflags |= znaf->za_flag;
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.
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;
871 * Fill in the ZFS-style ACE
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;
880 * Convert an internal SD to a ZFS-style ACL.
881 * Note optional args: vsa/acl, uidp, gidp.
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.
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)
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;
908 * sanity checks
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);
922 * How many SID mappings will we need?
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) {
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.
943 mapcnt = 1;
946 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
947 if (mapinfo == NULL) {
948 error = ENOMEM;
949 goto errout;
951 bzero(mapinfo, mapcnt * sizeof (*mapinfo));
955 * Get an imap "batch" request handle.
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;
965 #endif /* _KERNEL */
968 * Build our request to the idmap deamon,
969 * getting Unix IDs for every SID.
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++;
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++;
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++;
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++;
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;
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.
1027 mip = mapinfo;
1028 if (sd->sd_owner) {
1029 own_uid = mip->mi_uid;
1030 mip++;
1032 if (sd->sd_group) {
1033 own_gid = mip->mi_uid;
1034 mip++;
1037 if (uidp)
1038 *uidp = own_uid;
1039 if (gidp)
1040 *gidp = own_gid;
1042 if (acl_info == NULL) {
1043 /* Caller only wanted uid/gid */
1044 goto done;
1048 * Build the ZFS-style ACL
1049 * First, allocate the most ZFS ACEs we'll need.
1051 zacecnt = 0;
1052 if ((sd->sd_flags & SD_SACL_PRESENT) &&
1053 (sd->sd_sacl != NULL))
1054 zacecnt += sd->sd_sacl->acl_acecount;
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 {
1062 * DACL is NULL or empty. Either way,
1063 * we'll need to add a ZFS ACE below.
1065 zacecnt++;
1067 zacl_size = zacecnt * sizeof (ace_t);
1068 zacep0 = MALLOC(zacl_size);
1069 if (zacep0 == NULL) {
1070 error = ENOMEM;
1071 goto errout;
1073 zacep = zacep0;
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++;
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++;
1098 if (sd->sd_dacl == NULL) {
1100 * The SD has a NULL DACL. That means
1101 * everyone@, full-control
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) {
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.
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;
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 */
1129 done:
1130 error = 0;
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 */
1143 return (error);
1148 * ================================================================
1149 * Support for ACL store, including conversions
1150 * from NFSv4-style ACLs to Windows ACLs.
1151 * ================================================================
1155 * Convert a "sid-prefix" string plus RID into an NT SID.
1157 * If successful, sets *osid and returns zero,
1158 * otherwise returns an errno value.
1161 smbfs_str2sid(const char *sid_prefix, uint32_t *ridp, i_ntsid_t **osidp)
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;
1173 if (sid_prefix == NULL)
1174 return (EINVAL);
1176 p = sid_prefix;
1177 if (strncmp(p, "S-1-", 4) != 0)
1178 return (EINVAL);
1179 p += 4;
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 */
1193 * Count the sub-authorities. Here, np points to
1194 * the "-" before the first sub-authority.
1196 sacnt = 0;
1197 for (p = np; *p; p++) {
1198 if (*p == '-')
1199 sacnt++;
1201 if (ridp != NULL)
1202 sacnt++;
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);
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;
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;
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;
1239 #endif /* _KERNEL */
1240 sid->sid_subauthvec[i] = (uint32_t)sa;
1241 p = np;
1243 if (*p != '\0')
1244 goto out;
1245 if (ridp != NULL)
1246 sid->sid_subauthvec[i] = *ridp;
1247 err = 0;
1249 out:
1250 if (err)
1251 FREESZ(sid, size);
1252 else
1253 *osidp = sid;
1255 return (err);
1259 * The idmap API is _almost_ the same between
1260 * kernel and user-level. But not quite...
1261 * Hope this improves readability below.
1263 #ifdef _KERNEL
1265 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1266 kidmap_batch_getsidbyuid(GH, UID, SPP, RP, ST)
1268 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1269 kidmap_batch_getsidbygid(GH, GID, SPP, RP, ST)
1271 #else /* _KERNEL */
1273 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1274 idmap_get_sidbyuid(GH, UID, 0, SPP, RP, ST)
1276 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1277 idmap_get_sidbygid(GH, GID, 0, SPP, RP, ST)
1279 #endif /* _KERNEL */
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;
1293 * Build an idmap request. Cleanup is
1294 * handled by the caller (error or not)
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)
1303 idmap_stat idms;
1305 switch (req_type) {
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;
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;
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;
1328 default:
1329 idms = IDMAP_ERR_OTHER;
1330 break;
1333 if (idms != IDMAP_SUCCESS)
1334 return (EINVAL);
1336 return (0);
1340 * Convert a ZFS ACE to an NT ACE.
1341 * ACE type was already validated.
1343 static int
1344 zace2ntace(i_ntace_t **ntacep, ace_t *zacep, struct mapinfo2sid *mip)
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;
1354 if (mip->mi_dsid == NULL || mip->mi_status != 0) {
1355 return (EINVAL);
1359 * Translate ZFS ACE flags to NT ACE flags.
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;
1367 * The access rights bits are OK as-is.
1369 rights = zacep->a_access_mask;
1372 * Make sure we can get the SID.
1373 * Note: allocates sid.
1375 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, &sid);
1376 if (error)
1377 return (error);
1380 * Allocate the NT ACE and fill it in.
1382 alloc_size = sizeof (i_ntace_v2_t);
1383 if ((ntace = MALLOC(alloc_size)) == NULL) {
1384 ifree_sid(sid);
1385 return (ENOMEM);
1387 bzero(ntace, alloc_size);
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;
1395 *ntacep = ntace;
1396 return (0);
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.
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.
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)
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;
1436 * First, get all the UID+GID to SID mappings.
1437 * How many? Also sanity checks.
1439 mapcnt = 0;
1440 if (selector & OWNER_SECURITY_INFORMATION) {
1441 if (own_uid == (uid_t)-1)
1442 return (EINVAL);
1443 mapcnt++;
1445 if (selector & GROUP_SECURITY_INFORMATION) {
1446 if (own_gid == (gid_t)-1)
1447 return (EINVAL);
1448 mapcnt++;
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;
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 */
1483 * Get an imap "batch" request handle.
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;
1493 #endif /* _KERNEL */
1496 * Build our request to the idmap deamon,
1497 * getting SIDs for every Unix UID/GID.
1498 * Also count DACL and SACL ACEs here.
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++;
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++;
1515 if (selector & (DACL_SECURITY_INFORMATION |
1516 SACL_SECURITY_INFORMATION)) {
1517 int rqtype;
1518 uid_t uid;
1520 zacep = zacevec;
1521 for (i = 0; i < zacecnt; i++) {
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 */
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;
1555 error = mkrq_idmap_ux2sid(idmap_gh, mip, uid, rqtype);
1556 if (error)
1557 goto errout;
1558 zacep++;
1559 mip++;
1563 idms = I_getmappings(idmap_gh);
1564 if (idms != IDMAP_SUCCESS) {
1565 /* creative error choice */
1566 error = EIDRM;
1567 goto errout;
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.
1576 if ((sd = MALLOC(sizeof (*sd))) == NULL) {
1577 error = ENOMEM;
1578 goto errout;
1580 bzero(sd, sizeof (*sd));
1581 sd->sd_revision = NT_SD_REVISION;
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++;
1589 if (selector & GROUP_SECURITY_INFORMATION) {
1590 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1591 &sd->sd_group);
1592 mip++;
1596 * If setting both DACL and SACL, we will
1597 * make two passes starting here in mapinfo.
1599 mip_acl = mip;
1601 if (selector & DACL_SECURITY_INFORMATION) {
1603 * Caller wants to set the DACL.
1605 aclsz = I_ACL_SIZE(dacl_acecnt);
1606 if ((acl = MALLOC(aclsz)) == NULL) {
1607 error = ENOMEM;
1608 goto errout;
1610 bzero(acl, aclsz);
1612 acl->acl_revision = NT_ACL_REVISION;
1613 acl->acl_acecount = (uint16_t)dacl_acecnt;
1614 acep = &acl->acl_acevec[0];
1616 /* 1st pass - scan for DACL ACE types. */
1617 mip = mip_acl;
1618 zacep = zacevec;
1619 for (i = 0; i < zacecnt; i++) {
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;
1630 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1631 case ACE_SYSTEM_ALARM_ACE_TYPE:
1632 break;
1633 /* other types todo */
1635 zacep++;
1636 mip++;
1638 sd->sd_dacl = acl;
1639 acl = NULL;
1640 sd->sd_flags |= SD_DACL_PRESENT;
1643 if (selector & SACL_SECURITY_INFORMATION) {
1645 * Caller wants to set the SACL.
1647 aclsz = I_ACL_SIZE(sacl_acecnt);
1648 if ((acl = MALLOC(aclsz)) == NULL) {
1649 error = ENOMEM;
1650 goto errout;
1652 bzero(acl, aclsz);
1654 acl->acl_revision = NT_ACL_REVISION;
1655 acl->acl_acecount = (uint16_t)sacl_acecnt;
1656 acep = &acl->acl_acevec[0];
1658 /* 2nd pass - scan for SACL ACE types. */
1659 mip = mip_acl;
1660 zacep = zacevec;
1661 for (i = 0; i < zacecnt; i++) {
1663 switch (zacep->a_type) {
1664 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1665 case ACE_ACCESS_DENIED_ACE_TYPE:
1666 break;
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 */
1677 zacep++;
1678 mip++;
1680 sd->sd_sacl = acl;
1681 acl = NULL;
1682 sd->sd_flags |= SD_SACL_PRESENT;
1685 *sdp = sd;
1686 error = 0;
1688 errout:
1689 if (error != 0) {
1690 if (acl != NULL)
1691 ifree_acl(acl);
1692 if (sd != NULL)
1693 smbfs_acl_free_sd(sd);
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 */
1705 return (error);