dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / common / smbclnt / smbfs_ntacl.c
blob8d014d62ef5a1767a341c4bd2a2b060418bca32f
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 #define FREESZ(p, sz) free(p)
70 #endif /* _KERNEL */
72 #define ERRCHK(expr) if ((error = expr) != 0) goto errout
75 * Security IDentifier (SID)
77 static void
78 ifree_sid(i_ntsid_t *sid)
80 size_t sz;
82 if (sid == NULL)
83 return;
85 sz = I_SID_SIZE(sid->sid_subauthcount);
86 FREESZ(sid, sz);
89 static int
90 md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp)
92 i_ntsid_t *sid = NULL;
93 uint8_t revision, subauthcount;
94 uint32_t *subauthp;
95 size_t sidsz;
96 int error, i;
98 if ((error = md_get_uint8(mdp, &revision)) != 0)
99 return (error);
100 if ((error = md_get_uint8(mdp, &subauthcount)) != 0)
101 return (error);
103 sidsz = I_SID_SIZE(subauthcount);
105 if ((sid = MALLOC(sidsz)) == NULL)
106 return (ENOMEM);
108 bzero(sid, sidsz);
109 sid->sid_revision = revision;
110 sid->sid_subauthcount = subauthcount;
111 ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM));
113 subauthp = &sid->sid_subauthvec[0];
114 for (i = 0; i < subauthcount; i++) {
115 ERRCHK(md_get_uint32le(mdp, subauthp));
116 subauthp++;
119 /* Success! */
120 *sidp = sid;
121 return (0);
123 errout:
124 ifree_sid(sid);
125 return (error);
128 static int
129 mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid)
131 uint32_t *subauthp;
132 int error, i;
134 if (sid == NULL)
135 return (EINVAL);
137 ERRCHK(mb_put_uint8(mbp, sid->sid_revision));
138 ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount));
139 ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM));
141 subauthp = &sid->sid_subauthvec[0];
142 for (i = 0; i < sid->sid_subauthcount; i++) {
143 ERRCHK(mb_put_uint32le(mbp, *subauthp));
144 subauthp++;
147 /* Success! */
148 return (0);
150 errout:
151 return (error);
156 * Access Control Entry (ACE)
158 static void
159 ifree_ace(i_ntace_t *ace)
162 if (ace == NULL)
163 return;
165 switch (ace->ace_hdr.ace_type) {
166 case ACCESS_ALLOWED_ACE_TYPE:
167 case ACCESS_DENIED_ACE_TYPE:
168 case SYSTEM_AUDIT_ACE_TYPE:
169 case SYSTEM_ALARM_ACE_TYPE:
170 ifree_sid(ace->ace_v2.ace_sid);
171 FREESZ(ace, sizeof (i_ntace_v2_t));
172 break;
173 /* other types todo */
174 default:
175 break;
179 static int
180 md_get_ace(mdchain_t *mdp, i_ntace_t **acep)
182 mdchain_t tmp_md;
183 i_ntace_hdr_t ace_hdr;
184 i_ntace_t *ace = NULL;
185 uint16_t alloc_size;
186 int error;
189 * The ACE is realy variable length,
190 * with format determined by the type.
192 * There may also be padding after it, so
193 * decode it using a copy of the mdchain,
194 * and then consume the specified length.
196 tmp_md = *mdp;
198 /* Fixed-size ACE header */
199 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_type));
200 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_flags));
201 ERRCHK(md_get_uint16le(&tmp_md, &ace_hdr.ace_size));
203 switch (ace_hdr.ace_type) {
204 case ACCESS_ALLOWED_ACE_TYPE:
205 case ACCESS_DENIED_ACE_TYPE:
206 case SYSTEM_AUDIT_ACE_TYPE:
207 case SYSTEM_ALARM_ACE_TYPE:
208 alloc_size = sizeof (i_ntace_v2_t);
209 if ((ace = MALLOC(alloc_size)) == NULL)
210 return (ENOMEM);
211 bzero(ace, alloc_size);
212 /* ACE header */
213 ace->ace_hdr.ace_type = ace_hdr.ace_type;
214 ace->ace_hdr.ace_flags = ace_hdr.ace_flags;
215 ace->ace_hdr.ace_size = alloc_size;
216 /* Type-specific data. */
217 ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_v2.ace_rights));
218 ERRCHK(md_get_sid(&tmp_md, &ace->ace_v2.ace_sid));
219 break;
221 /* other types todo */
222 default:
223 error = EIO;
224 goto errout;
227 /* Now actually consume ace_hdr.ace_size */
228 ERRCHK(md_get_mem(mdp, NULL, ace_hdr.ace_size, MB_MSYSTEM));
230 /* Success! */
231 *acep = ace;
232 return (0);
234 errout:
235 ifree_ace(ace);
236 return (error);
239 static int
240 mb_put_ace(mbchain_t *mbp, i_ntace_t *ace)
242 int cnt0, error;
243 uint16_t ace_len, *ace_len_p;
245 if (ace == NULL)
246 return (EINVAL);
248 cnt0 = mbp->mb_count;
251 * Put the (fixed-size) ACE header
252 * Will fill in the length later.
254 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_type));
255 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_flags));
256 ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p));
257 if (ace_len_p == NULL) {
258 error = ENOMEM;
259 goto errout;
262 switch (ace->ace_hdr.ace_type) {
263 case ACCESS_ALLOWED_ACE_TYPE:
264 case ACCESS_DENIED_ACE_TYPE:
265 case SYSTEM_AUDIT_ACE_TYPE:
266 case SYSTEM_ALARM_ACE_TYPE:
267 /* Put type-specific data. */
268 ERRCHK(mb_put_uint32le(mbp, ace->ace_v2.ace_rights));
269 ERRCHK(mb_put_sid(mbp, ace->ace_v2.ace_sid));
270 break;
272 /* other types todo */
273 default:
274 error = EIO;
275 goto errout;
278 /* Fill in the (OtW) ACE length. */
279 ace_len = mbp->mb_count - cnt0;
280 *ace_len_p = htoles(ace_len);
282 /* Success! */
283 return (0);
285 errout:
286 return (error);
291 * Access Control List (ACL)
294 /* Not an OTW structure, so size can be at our convenience. */
295 #define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *))
297 static void
298 ifree_acl(i_ntacl_t *acl)
300 i_ntace_t **acep;
301 size_t sz;
302 int i;
304 if (acl == NULL)
305 return;
307 acep = &acl->acl_acevec[0];
308 for (i = 0; i < acl->acl_acecount; i++) {
309 ifree_ace(*acep);
310 acep++;
312 sz = I_ACL_SIZE(acl->acl_acecount);
313 FREESZ(acl, sz);
316 static int
317 md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp)
319 i_ntacl_t *acl = NULL;
320 i_ntace_t **acep;
321 uint8_t revision;
322 uint16_t acl_len, acecount;
323 size_t aclsz;
324 int i, error;
326 if ((error = md_get_uint8(mdp, &revision)) != 0)
327 return (error);
328 if ((error = md_get_uint8(mdp, NULL)) != 0) /* pad1 */
329 return (error);
330 if ((error = md_get_uint16le(mdp, &acl_len)) != 0)
331 return (error);
332 if ((error = md_get_uint16le(mdp, &acecount)) != 0)
333 return (error);
334 if ((error = md_get_uint16le(mdp, NULL)) != 0) /* pad2 */
335 return (error);
337 aclsz = I_ACL_SIZE(acecount);
338 if ((acl = MALLOC(aclsz)) == NULL)
339 return (ENOMEM);
340 bzero(acl, aclsz);
341 acl->acl_revision = revision;
342 acl->acl_acecount = acecount;
344 acep = &acl->acl_acevec[0];
345 for (i = 0; i < acl->acl_acecount; i++) {
346 ERRCHK(md_get_ace(mdp, acep));
347 acep++;
350 * There may be more data here, but
351 * the caller takes care of that.
354 /* Success! */
355 *aclp = acl;
356 return (0);
358 errout:
359 ifree_acl(acl);
360 return (error);
363 static int
364 mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl)
366 i_ntace_t **acep;
367 uint16_t acl_len, *acl_len_p;
368 int i, cnt0, error;
370 cnt0 = mbp->mb_count;
372 ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
373 ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
374 acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p));
375 if (acl_len_p == NULL) {
376 error = ENOMEM;
377 goto errout;
379 ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
380 ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
382 acep = &acl->acl_acevec[0];
383 for (i = 0; i < acl->acl_acecount; i++) {
384 ERRCHK(mb_put_ace(mbp, *acep));
385 acep++;
388 /* Fill in acl_len_p */
389 acl_len = mbp->mb_count - cnt0;
390 *acl_len_p = htoles(acl_len);
392 /* Success! */
393 return (0);
395 errout:
396 return (error);
401 * Security Descriptor
403 void
404 smbfs_acl_free_sd(i_ntsd_t *sd)
407 if (sd == NULL)
408 return;
410 ifree_sid(sd->sd_owner);
411 ifree_sid(sd->sd_group);
412 ifree_acl(sd->sd_sacl);
413 ifree_acl(sd->sd_dacl);
415 FREESZ(sd, sizeof (*sd));
419 * Import a raw SD (mb chain) into "internal" form.
420 * (like "absolute" form per. NT docs)
421 * Returns allocated data in sdp
423 * Note: does NOT consume all the mdp data, so the
424 * caller has to take care of that if necessary.
427 md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp)
429 i_ntsd_t *sd = NULL;
430 mdchain_t top_md, tmp_md;
431 uint32_t owneroff, groupoff, sacloff, dacloff;
432 int error;
434 if ((sd = MALLOC(sizeof (*sd))) == NULL)
435 return (ENOMEM);
436 bzero(sd, sizeof (*sd));
439 * Offsets below are relative to this point,
440 * so save the mdp state for use below.
442 top_md = *mdp;
444 ERRCHK(md_get_uint8(mdp, &sd->sd_revision));
445 ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl));
446 ERRCHK(md_get_uint16le(mdp, &sd->sd_flags));
447 ERRCHK(md_get_uint32le(mdp, &owneroff));
448 ERRCHK(md_get_uint32le(mdp, &groupoff));
449 ERRCHK(md_get_uint32le(mdp, &sacloff));
450 ERRCHK(md_get_uint32le(mdp, &dacloff));
453 * The SD is "self-relative" on the wire,
454 * but not after this decodes it.
456 sd->sd_flags &= ~SD_SELF_RELATIVE;
459 * For each section make a temporary copy of the
460 * top_md state, advance to the given offset, and
461 * pass that to the lower md_get_xxx functions.
462 * These could be marshalled in any order, but
463 * are normally found in the order shown here.
465 if (sacloff) {
466 tmp_md = top_md;
467 md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM);
468 ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl));
470 if (dacloff) {
471 tmp_md = top_md;
472 md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM);
473 ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl));
475 if (owneroff) {
476 tmp_md = top_md;
477 md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM);
478 ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner));
480 if (groupoff) {
481 tmp_md = top_md;
482 md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM);
483 ERRCHK(md_get_sid(&tmp_md, &sd->sd_group));
486 /* Success! */
487 *sdp = sd;
488 return (0);
490 errout:
491 smbfs_acl_free_sd(sd);
492 return (error);
496 * Export an "internal" SD into an raw SD (mb chain).
497 * (a.k.a "self-relative" form per. NT docs)
498 * Returns allocated mbchain in mbp.
501 mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd)
503 uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
504 uint32_t owneroff, groupoff, sacloff, dacloff;
505 uint16_t flags;
506 int cnt0, error;
508 cnt0 = mbp->mb_count;
509 owneroff = groupoff = sacloff = dacloff = 0;
511 /* The SD is "self-relative" on the wire. */
512 flags = sd->sd_flags | SD_SELF_RELATIVE;
514 ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
515 ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl));
516 ERRCHK(mb_put_uint16le(mbp, flags));
518 owneroffp = mb_reserve(mbp, sizeof (*owneroffp));
519 groupoffp = mb_reserve(mbp, sizeof (*groupoffp));
520 sacloffp = mb_reserve(mbp, sizeof (*sacloffp));
521 dacloffp = mb_reserve(mbp, sizeof (*dacloffp));
522 if (owneroffp == NULL || groupoffp == NULL ||
523 sacloffp == NULL || dacloffp == NULL) {
524 error = ENOMEM;
525 goto errout;
529 * These could be marshalled in any order, but
530 * are normally found in the order shown here.
532 if (sd->sd_sacl) {
533 sacloff = mbp->mb_count - cnt0;
534 ERRCHK(mb_put_acl(mbp, sd->sd_sacl));
536 if (sd->sd_dacl) {
537 dacloff = mbp->mb_count - cnt0;
538 ERRCHK(mb_put_acl(mbp, sd->sd_dacl));
540 if (sd->sd_owner) {
541 owneroff = mbp->mb_count - cnt0;
542 ERRCHK(mb_put_sid(mbp, sd->sd_owner));
544 if (sd->sd_group) {
545 groupoff = mbp->mb_count - cnt0;
546 ERRCHK(mb_put_sid(mbp, sd->sd_group));
549 /* Fill in the offsets */
550 *owneroffp = htolel(owneroff);
551 *groupoffp = htolel(groupoff);
552 *sacloffp = htolel(sacloff);
553 *dacloffp = htolel(dacloff);
555 /* Success! */
556 return (0);
558 errout:
559 return (error);
563 * ================================================================
564 * Support for ACL fetch, including conversions
565 * from Windows ACLs to NFSv4-style ACLs.
566 * ================================================================
569 #define GENERIC_RIGHTS_MASK \
570 (GENERIC_RIGHT_READ_ACCESS | GENERIC_RIGHT_WRITE_ACCESS |\
571 GENERIC_RIGHT_EXECUTE_ACCESS | GENERIC_RIGHT_ALL_ACCESS)
574 * Table for converting NT GENERIC_RIGHT_... to specific rights
575 * appropriate for objects of type file.
577 struct gen2fsr {
578 uint32_t gf_generic;
579 uint32_t gf_specific;
581 static const struct gen2fsr
582 smbfs_gen2fsr[] = {
584 GENERIC_RIGHT_READ_ACCESS,
585 STD_RIGHT_SYNCHRONIZE_ACCESS |
586 STD_RIGHT_READ_CONTROL_ACCESS |
587 SA_RIGHT_FILE_READ_ATTRIBUTES |
588 SA_RIGHT_FILE_READ_EA |
589 SA_RIGHT_FILE_READ_DATA },
591 GENERIC_RIGHT_WRITE_ACCESS,
592 STD_RIGHT_SYNCHRONIZE_ACCESS |
593 STD_RIGHT_READ_CONTROL_ACCESS |
594 SA_RIGHT_FILE_WRITE_ATTRIBUTES |
595 SA_RIGHT_FILE_WRITE_EA |
596 SA_RIGHT_FILE_APPEND_DATA |
597 SA_RIGHT_FILE_WRITE_DATA },
599 GENERIC_RIGHT_EXECUTE_ACCESS,
600 STD_RIGHT_SYNCHRONIZE_ACCESS |
601 STD_RIGHT_READ_CONTROL_ACCESS |
602 SA_RIGHT_FILE_READ_ATTRIBUTES |
603 SA_RIGHT_FILE_EXECUTE },
605 GENERIC_RIGHT_ALL_ACCESS,
606 STD_RIGHT_SYNCHRONIZE_ACCESS |
607 STD_RIGHT_WRITE_OWNER_ACCESS |
608 STD_RIGHT_WRITE_DAC_ACCESS |
609 STD_RIGHT_READ_CONTROL_ACCESS |
610 STD_RIGHT_DELETE_ACCESS |
611 SA_RIGHT_FILE_ALL_ACCESS },
612 { 0, 0 }
616 * Table for translating ZFS ACE flags to NT ACE flags.
617 * The low four bits are the same, but not others.
619 struct zaf2naf {
620 uint16_t za_flag;
621 uint8_t na_flag;
623 static const struct zaf2naf
624 smbfs_zaf2naf[] = {
625 { ACE_FILE_INHERIT_ACE, OBJECT_INHERIT_ACE_FLAG },
626 { ACE_DIRECTORY_INHERIT_ACE, CONTAINER_INHERIT_ACE_FLAG },
627 { ACE_NO_PROPAGATE_INHERIT_ACE, NO_PROPAGATE_INHERIT_ACE_FLAG },
628 { ACE_INHERIT_ONLY_ACE, INHERIT_ONLY_ACE_FLAG },
629 { ACE_INHERITED_ACE, INHERITED_ACE_FLAG },
630 { ACE_SUCCESSFUL_ACCESS_ACE_FLAG, SUCCESSFUL_ACCESS_ACE_FLAG },
631 { ACE_FAILED_ACCESS_ACE_FLAG, FAILED_ACCESS_ACE_FLAG },
632 { 0, 0 }
636 * Convert an NT SID to a string. Optionally return the
637 * last sub-authority (or "relative ID" -- RID) in *ridp
638 * and truncate the output string after the domain part.
639 * If ridp==NULL, the output string is the whole SID,
640 * including both the domain and RID.
642 * Return length written, or -1 on error.
645 smbfs_sid2str(i_ntsid_t *sid,
646 char *obuf, size_t osz, uint32_t *ridp)
648 char *s = obuf;
649 uint64_t auth = 0;
650 uint_t i, n;
651 uint32_t subs, *ip;
653 n = snprintf(s, osz, "S-%u", sid->sid_revision);
654 if (n > osz)
655 return (-1);
656 s += n; osz -= n;
658 for (i = 0; i < 6; i++)
659 auth = (auth << 8) | sid->sid_authority[i];
660 n = snprintf(s, osz, "-%llu", (u_longlong_t)auth);
661 if (n > osz)
662 return (-1);
663 s += n; osz -= n;
665 subs = sid->sid_subauthcount;
666 if (subs < 1 || subs > 15)
667 return (-1);
668 if (ridp)
669 subs--;
671 ip = &sid->sid_subauthvec[0];
672 for (; subs; subs--, ip++) {
673 n = snprintf(s, osz, "-%u", *ip);
674 if (n > osz)
675 return (-1);
676 s += n; osz -= n;
678 if (ridp)
679 *ridp = *ip;
681 /* LINTED E_PTRDIFF_OVERFLOW */
682 return (s - obuf);
686 * Our interface to the idmap service.
688 * The idmap API is _almost_ the same between
689 * kernel and user-level. But not quite...
690 * Hope this improves readability below.
692 #ifdef _KERNEL
694 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
695 kidmap_batch_getuidbysid(GH, SPP, RID, UIDP, SP)
697 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
698 kidmap_batch_getgidbysid(GH, SPP, RID, GIDP, SP)
700 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
701 kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP)
703 #define I_getmappings kidmap_get_mappings
705 #else /* _KERNEL */
707 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
708 idmap_get_uidbysid(GH, SPP, RID, 0, UIDP, SP)
710 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
711 idmap_get_gidbysid(GH, SPP, RID, 0, GIDP, SP)
713 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
714 idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP)
716 #define I_getmappings idmap_get_mappings
718 #endif /* _KERNEL */
722 * The idmap request types, chosen so they also
723 * match the values returned in mi_isuser.
725 #define IDM_TYPE_ANY -1
726 #define IDM_TYPE_GROUP 0
727 #define IDM_TYPE_USER 1
730 * A sentinel value for mi_isuser (below) to indicate
731 * that the SID is the well-known "Everyone" (S-1-1-0).
732 * The idmap library only uses -1, 0, 1, so this value
733 * is arbitrary but must not overlap w/ idmap values.
734 * XXX: Could use a way for idmap to tell us when
735 * it recognizes this well-known SID.
737 #define IDM_EVERYONE 11
739 struct mapinfo2uid {
740 uid_t mi_uid; /* or gid, or pid */
741 int mi_isuser; /* IDM_TYPE */
742 idmap_stat mi_status;
746 * Build an idmap request. Cleanup is
747 * handled by the caller (error or not)
749 static int
750 mkrq_idmap_sid2ux(
751 idmap_get_handle_t *idmap_gh,
752 struct mapinfo2uid *mip,
753 i_ntsid_t *sid,
754 int req_type)
756 char strbuf[256];
757 char *sid_prefix;
758 uint32_t rid;
759 idmap_stat idms;
761 if (smbfs_sid2str(sid, strbuf, sizeof (strbuf), &rid) < 0)
762 return (EINVAL);
763 sid_prefix = strbuf;
766 * Give the "Everyone" group special treatment.
768 if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) {
769 /* This is "Everyone" */
770 mip->mi_uid = (uid_t)-1;
771 mip->mi_isuser = IDM_EVERYONE;
772 mip->mi_status = 0;
773 return (0);
776 switch (req_type) {
778 case IDM_TYPE_USER:
779 mip->mi_isuser = req_type;
780 idms = I_getuidbysid(idmap_gh, sid_prefix, rid,
781 &mip->mi_uid, &mip->mi_status);
782 break;
784 case IDM_TYPE_GROUP:
785 mip->mi_isuser = req_type;
786 idms = I_getgidbysid(idmap_gh, sid_prefix, rid,
787 &mip->mi_uid, &mip->mi_status);
788 break;
790 case IDM_TYPE_ANY:
791 idms = I_getpidbysid(idmap_gh, sid_prefix, rid,
792 &mip->mi_uid, &mip->mi_isuser, &mip->mi_status);
793 break;
795 default:
796 idms = IDMAP_ERR_OTHER;
797 break;
800 if (idms != IDMAP_SUCCESS)
801 return (EINVAL);
803 return (0);
807 * Convert an NT ACE to a ZFS ACE.
808 * ACE type was already validated.
810 static void
811 ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo2uid *mip)
813 const struct zaf2naf *znaf;
814 uid_t zwho;
815 uint32_t zamask;
816 uint16_t zflags;
819 * Set the "ID type" flags in the ZFS ace flags.
821 zflags = 0;
822 switch (mip->mi_isuser) {
823 case IDM_EVERYONE:
824 zflags = ACE_EVERYONE;
825 zwho = (uid_t)-1;
826 break;
828 case IDM_TYPE_GROUP: /* it's a GID */
829 zflags = ACE_IDENTIFIER_GROUP;
830 zwho = mip->mi_uid;
831 break;
833 default:
834 case IDM_TYPE_USER: /* it's a UID */
835 zflags = 0;
836 zwho = mip->mi_uid;
837 break;
841 * Translate NT ACE flags to ZFS ACE flags.
843 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
844 if (ntace->ace_hdr.ace_flags & znaf->na_flag)
845 zflags |= znaf->za_flag;
848 * The "normal" access mask bits are the same, but
849 * if the ACE has any GENERIC_RIGHT_... convert those
850 * to specific rights. GENERIC bits are rarely seen,
851 * but reportedly can happen with inherit-only ACEs.
853 zamask = ntace->ace_v2.ace_rights & ACE_ALL_PERMS;
854 if (ntace->ace_v2.ace_rights & GENERIC_RIGHTS_MASK) {
855 const struct gen2fsr *gf;
856 for (gf = smbfs_gen2fsr; gf->gf_generic; gf++)
857 if (ntace->ace_v2.ace_rights & gf->gf_generic)
858 zamask |= gf->gf_specific;
862 * Fill in the ZFS-style ACE
864 zacep->a_who = zwho;
865 zacep->a_access_mask = zamask;
866 zacep->a_flags = zflags;
867 zacep->a_type = ntace->ace_hdr.ace_type;
871 * Convert an internal SD to a ZFS-style ACL.
872 * Note optional args: vsa/acl, uidp, gidp.
874 * This makes two passes over the SD, the first building a
875 * "batch" request for idmap with results in mapinfo, the
876 * second building a ZFS-style ACL using the idmap results.
879 smbfs_acl_sd2zfs(
880 i_ntsd_t *sd,
881 #ifdef _KERNEL
882 vsecattr_t *acl_info,
883 #else /* _KERNEL */
884 acl_t *acl_info,
885 #endif /* _KERNEL */
886 uid_t *uidp, gid_t *gidp)
888 struct mapinfo2uid *mip, *mapinfo = NULL;
889 int error, i, mapcnt, zacecnt, zacl_size;
890 ace_t *zacep0, *zacep;
891 uid_t own_uid = (uid_t)-1;
892 gid_t own_gid = (gid_t)-1;
893 i_ntacl_t *ntacl;
894 i_ntace_t **ntacep;
895 idmap_get_handle_t *idmap_gh = NULL;
896 idmap_stat idms;
899 * sanity checks
901 if (acl_info) {
902 #ifndef _KERNEL
903 if (acl_info->acl_type != ACE_T ||
904 acl_info->acl_aclp != NULL ||
905 acl_info->acl_entry_size != sizeof (ace_t))
906 return (EINVAL);
907 #endif /* _KERNEL */
908 if ((sd->sd_flags & SD_DACL_PRESENT) == 0)
909 return (EINVAL);
913 * How many SID mappings will we need?
915 mapcnt = 0;
916 if (sd->sd_owner)
917 mapcnt++;
918 if (sd->sd_group)
919 mapcnt++;
920 if ((sd->sd_flags & SD_SACL_PRESENT) &&
921 (sd->sd_sacl != NULL))
922 mapcnt += sd->sd_sacl->acl_acecount;
923 if ((sd->sd_flags & SD_DACL_PRESENT) &&
924 (sd->sd_dacl != NULL))
925 mapcnt += sd->sd_dacl->acl_acecount;
926 if (mapcnt == 0) {
928 * We have a NULL DACL, SACL, and don't
929 * have an owner or group, so there's no
930 * idmap work to do. This is very rare,
931 * so rather than complicate things below,
932 * pretend we need one mapping slot.
934 mapcnt = 1;
937 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
938 if (mapinfo == NULL) {
939 error = ENOMEM;
940 goto errout;
942 bzero(mapinfo, mapcnt * sizeof (*mapinfo));
946 * Get an imap "batch" request handle.
948 #ifdef _KERNEL
949 idmap_gh = kidmap_get_create(curproc->p_zone);
950 #else /* _KERNEL */
951 idms = idmap_get_create(&idmap_gh);
952 if (idms != IDMAP_SUCCESS) {
953 error = ENOTACTIVE;
954 goto errout;
956 #endif /* _KERNEL */
959 * Build our request to the idmap deamon,
960 * getting Unix IDs for every SID.
962 mip = mapinfo;
963 if (sd->sd_owner) {
964 error = mkrq_idmap_sid2ux(idmap_gh, mip,
965 sd->sd_owner, IDM_TYPE_USER);
966 if (error)
967 goto errout;
968 mip++;
970 if (sd->sd_group) {
971 error = mkrq_idmap_sid2ux(idmap_gh, mip,
972 sd->sd_group, IDM_TYPE_GROUP);
973 if (error)
974 goto errout;
975 mip++;
977 if ((sd->sd_flags & SD_SACL_PRESENT) &&
978 (sd->sd_sacl != NULL)) {
979 ntacl = sd->sd_sacl;
980 ntacep = &ntacl->acl_acevec[0];
981 for (i = 0; i < ntacl->acl_acecount; i++) {
982 error = mkrq_idmap_sid2ux(idmap_gh, mip,
983 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
984 if (error)
985 goto errout;
986 ntacep++;
987 mip++;
990 if ((sd->sd_flags & SD_DACL_PRESENT) &&
991 (sd->sd_dacl != NULL)) {
992 ntacl = sd->sd_dacl;
993 ntacep = &ntacl->acl_acevec[0];
994 for (i = 0; i < ntacl->acl_acecount; i++) {
995 error = mkrq_idmap_sid2ux(idmap_gh, mip,
996 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
997 if (error)
998 goto errout;
999 ntacep++;
1000 mip++;
1004 if (mip != mapinfo) {
1005 idms = I_getmappings(idmap_gh);
1006 if (idms != IDMAP_SUCCESS) {
1007 /* creative error choice */
1008 error = EIDRM;
1009 goto errout;
1014 * With any luck, we now have Unix user/group IDs
1015 * for every Windows SID in the security descriptor.
1016 * The remaining work is just format conversion.
1018 mip = mapinfo;
1019 if (sd->sd_owner) {
1020 own_uid = mip->mi_uid;
1021 mip++;
1023 if (sd->sd_group) {
1024 own_gid = mip->mi_uid;
1025 mip++;
1028 if (uidp)
1029 *uidp = own_uid;
1030 if (gidp)
1031 *gidp = own_gid;
1033 if (acl_info == NULL) {
1034 /* Caller only wanted uid/gid */
1035 goto done;
1039 * Build the ZFS-style ACL
1040 * First, allocate the most ZFS ACEs we'll need.
1042 zacecnt = 0;
1043 if ((sd->sd_flags & SD_SACL_PRESENT) &&
1044 (sd->sd_sacl != NULL))
1045 zacecnt += sd->sd_sacl->acl_acecount;
1047 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1048 if ((sd->sd_dacl != NULL) &&
1049 (sd->sd_dacl->acl_acecount > 0)) {
1050 zacecnt += sd->sd_dacl->acl_acecount;
1051 } else {
1053 * DACL is NULL or empty. Either way,
1054 * we'll need to add a ZFS ACE below.
1056 zacecnt++;
1058 zacl_size = zacecnt * sizeof (ace_t);
1059 zacep0 = MALLOC(zacl_size);
1060 if (zacep0 == NULL) {
1061 error = ENOMEM;
1062 goto errout;
1064 zacep = zacep0;
1066 if ((sd->sd_flags & SD_SACL_PRESENT) &&
1067 (sd->sd_sacl != NULL)) {
1068 ntacl = sd->sd_sacl;
1069 ntacep = &ntacl->acl_acevec[0];
1070 for (i = 0; i < ntacl->acl_acecount; i++) {
1071 ntace2zace(zacep, *ntacep, mip);
1072 zacep++;
1073 ntacep++;
1074 mip++;
1078 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1079 if (sd->sd_dacl != NULL) {
1080 ntacl = sd->sd_dacl;
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++;
1089 if (sd->sd_dacl == NULL) {
1091 * The SD has a NULL DACL. That means
1092 * everyone@, full-control
1094 zacep->a_who = (uid_t)-1;
1095 zacep->a_access_mask = ACE_ALL_PERMS;
1096 zacep->a_flags = ACE_EVERYONE;
1097 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1098 } else if (sd->sd_dacl->acl_acecount == 0) {
1100 * The SD has an Empty DACL. We need
1101 * at least one ACE, so add one giving
1102 * the owner the usual implied access.
1104 zacep->a_who = (uid_t)-1;
1105 zacep->a_access_mask = ACE_READ_ATTRIBUTES | \
1106 ACE_READ_ACL | ACE_WRITE_ACL;
1107 zacep->a_flags = ACE_OWNER;
1108 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1111 #ifdef _KERNEL
1112 acl_info->vsa_aclcnt = zacecnt;
1113 acl_info->vsa_aclentp = zacep0;
1114 acl_info->vsa_aclentsz = zacl_size;
1115 #else /* _KERNEL */
1116 acl_info->acl_cnt = zacecnt;
1117 acl_info->acl_aclp = zacep0;
1118 #endif /* _KERNEL */
1120 done:
1121 error = 0;
1123 errout:
1124 if (mapinfo != NULL)
1125 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1126 #ifdef _KERNEL
1127 if (idmap_gh != NULL)
1128 kidmap_get_destroy(idmap_gh);
1129 #else /* _KERNEL */
1130 if (idmap_gh != NULL)
1131 idmap_get_destroy(idmap_gh);
1132 #endif /* _KERNEL */
1134 return (error);
1139 * ================================================================
1140 * Support for ACL store, including conversions
1141 * from NFSv4-style ACLs to Windows ACLs.
1142 * ================================================================
1146 * Convert a "sid-prefix" string plus RID into an NT SID.
1148 * If successful, sets *osid and returns zero,
1149 * otherwise returns an errno value.
1152 smbfs_str2sid(const char *sid_prefix, uint32_t *ridp, i_ntsid_t **osidp)
1154 i_ntsid_t *sid = NULL;
1155 u_longlong_t auth = 0;
1156 ulong_t sa;
1157 uint8_t sacnt;
1158 const char *p;
1159 char *np;
1160 size_t size;
1161 int i;
1162 int err;
1164 if (sid_prefix == NULL)
1165 return (EINVAL);
1167 p = sid_prefix;
1168 if (strncmp(p, "S-1-", 4) != 0)
1169 return (EINVAL);
1170 p += 4;
1172 /* Parse the "authority" */
1173 #ifdef _KERNEL
1174 err = ddi_strtoull(p, &np, 10, &auth);
1175 if (err != 0)
1176 return (err);
1177 #else /* _KERNEL */
1178 auth = strtoull(p, &np, 10);
1179 if (p == np)
1180 return (EINVAL);
1181 #endif /* _KERNEL */
1184 * Count the sub-authorities. Here, np points to
1185 * the "-" before the first sub-authority.
1187 sacnt = 0;
1188 for (p = np; *p; p++) {
1189 if (*p == '-')
1190 sacnt++;
1192 if (ridp != NULL)
1193 sacnt++;
1195 /* Allocate the internal SID. */
1196 size = I_SID_SIZE(sacnt);
1197 sid = MALLOC(size);
1198 if (sid == NULL)
1199 return (ENOMEM);
1200 bzero(sid, size);
1202 /* Fill it in. */
1203 sid->sid_revision = 1;
1204 sid->sid_subauthcount = sacnt;
1205 for (i = 5; i >= 0; i--) {
1206 sid->sid_authority[i] = auth & 0xFF;
1207 auth = auth >> 8;
1210 err = EINVAL;
1211 if (ridp != NULL)
1212 sacnt--; /* Last SA not from string */
1213 p = np;
1214 for (i = 0; i < sacnt; i++) {
1215 if (*p != '-') {
1216 err = EINVAL;
1217 goto out;
1219 p++;
1220 #ifdef _KERNEL
1221 err = ddi_strtoul(p, &np, 10, &sa);
1222 if (err != 0)
1223 goto out;
1224 #else /* _KERNEL */
1225 sa = strtoul(p, &np, 10);
1226 if (p == np) {
1227 err = EINVAL;
1228 goto out;
1230 #endif /* _KERNEL */
1231 sid->sid_subauthvec[i] = (uint32_t)sa;
1232 p = np;
1234 if (*p != '\0')
1235 goto out;
1236 if (ridp != NULL)
1237 sid->sid_subauthvec[i] = *ridp;
1238 err = 0;
1240 out:
1241 if (err)
1242 FREESZ(sid, size);
1243 else
1244 *osidp = sid;
1246 return (err);
1250 * The idmap API is _almost_ the same between
1251 * kernel and user-level. But not quite...
1252 * Hope this improves readability below.
1254 #ifdef _KERNEL
1256 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1257 kidmap_batch_getsidbyuid(GH, UID, SPP, RP, ST)
1259 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1260 kidmap_batch_getsidbygid(GH, GID, SPP, RP, ST)
1262 #else /* _KERNEL */
1264 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1265 idmap_get_sidbyuid(GH, UID, 0, SPP, RP, ST)
1267 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1268 idmap_get_sidbygid(GH, GID, 0, SPP, RP, ST)
1270 #endif /* _KERNEL */
1272 struct mapinfo2sid {
1273 /* Yet another kernel vs. user difference. */
1274 #ifdef _KERNEL
1275 const char *mi_dsid; /* domain SID */
1276 #else /* _KERNEL */
1277 char *mi_dsid;
1278 #endif /* _KERNEL */
1279 uint32_t mi_rid; /* relative ID */
1280 idmap_stat mi_status;
1284 * Build an idmap request. Cleanup is
1285 * handled by the caller (error or not)
1287 static int
1288 mkrq_idmap_ux2sid(
1289 idmap_get_handle_t *idmap_gh,
1290 struct mapinfo2sid *mip,
1291 uid_t uid, /* or gid */
1292 int req_type)
1294 idmap_stat idms;
1296 switch (req_type) {
1298 case IDM_TYPE_USER:
1299 if (uid == (uid_t)-1)
1300 return (EINVAL);
1301 idms = I_getsidbyuid(idmap_gh, uid,
1302 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1303 break;
1305 case IDM_TYPE_GROUP:
1306 if (uid == (uid_t)-1)
1307 return (EINVAL);
1308 idms = I_getsidbygid(idmap_gh, uid,
1309 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1310 break;
1312 case IDM_EVERYONE:
1313 mip->mi_dsid = "S-1-1";
1314 mip->mi_rid = 0;
1315 mip->mi_status = 0;
1316 idms = IDMAP_SUCCESS;
1317 break;
1319 default:
1320 idms = IDMAP_ERR_OTHER;
1321 break;
1324 if (idms != IDMAP_SUCCESS)
1325 return (EINVAL);
1327 return (0);
1331 * Convert a ZFS ACE to an NT ACE.
1332 * ACE type was already validated.
1334 static int
1335 zace2ntace(i_ntace_t **ntacep, ace_t *zacep, struct mapinfo2sid *mip)
1337 const struct zaf2naf *znaf;
1338 uint8_t aflags;
1339 uint16_t alloc_size;
1340 uint32_t rights;
1341 i_ntace_t *ntace = NULL;
1342 i_ntsid_t *sid = NULL;
1343 int error;
1345 if (mip->mi_dsid == NULL || mip->mi_status != 0) {
1346 return (EINVAL);
1350 * Translate ZFS ACE flags to NT ACE flags.
1352 aflags = 0;
1353 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
1354 if (zacep->a_flags & znaf->za_flag)
1355 aflags |= znaf->na_flag;
1358 * The access rights bits are OK as-is.
1360 rights = zacep->a_access_mask;
1363 * Make sure we can get the SID.
1364 * Note: allocates sid.
1366 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, &sid);
1367 if (error)
1368 return (error);
1371 * Allocate the NT ACE and fill it in.
1373 alloc_size = sizeof (i_ntace_v2_t);
1374 if ((ntace = MALLOC(alloc_size)) == NULL) {
1375 ifree_sid(sid);
1376 return (ENOMEM);
1378 bzero(ntace, alloc_size);
1380 ntace->ace_hdr.ace_type = zacep->a_type;
1381 ntace->ace_hdr.ace_flags = aflags;
1382 ntace->ace_hdr.ace_size = alloc_size;
1383 ntace->ace_v2.ace_rights = rights;
1384 ntace->ace_v2.ace_sid = sid;
1386 *ntacep = ntace;
1387 return (0);
1391 * Convert a ZFS-style ACL to an internal SD.
1392 * Set owner/group too if selector indicates.
1393 * Always need to pass uid+gid, either the new
1394 * (when setting them) or existing, so that any
1395 * owner@ or group@ ACEs can be translated.
1397 * This makes two passes over the ZFS ACL. The first builds a
1398 * "batch" request for idmap with results in mapinfo, and the
1399 * second builds the NT SD using the idmap SID results.
1402 smbfs_acl_zfs2sd(
1403 #ifdef _KERNEL
1404 vsecattr_t *acl_info,
1405 #else /* _KERNEL */
1406 acl_t *acl_info,
1407 #endif /* _KERNEL */
1408 uid_t own_uid,
1409 gid_t own_gid,
1410 uint32_t selector,
1411 i_ntsd_t **sdp)
1413 struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL;
1414 int aclsz, error, i, mapcnt;
1415 int dacl_acecnt = 0;
1416 int sacl_acecnt = 0;
1417 int zacecnt = 0;
1418 ace_t *zacevec = NULL;
1419 ace_t *zacep;
1420 i_ntsd_t *sd = NULL;
1421 i_ntacl_t *acl = NULL;
1422 i_ntace_t **acep = NULL;
1423 idmap_get_handle_t *idmap_gh = NULL;
1424 idmap_stat idms;
1427 * First, get all the UID+GID to SID mappings.
1428 * How many? Also sanity checks.
1430 mapcnt = 0;
1431 if (selector & OWNER_SECURITY_INFORMATION) {
1432 if (own_uid == (uid_t)-1)
1433 return (EINVAL);
1434 mapcnt++;
1436 if (selector & GROUP_SECURITY_INFORMATION) {
1437 if (own_gid == (gid_t)-1)
1438 return (EINVAL);
1439 mapcnt++;
1441 if (selector & (DACL_SECURITY_INFORMATION |
1442 SACL_SECURITY_INFORMATION)) {
1443 if (acl_info == NULL)
1444 return (EINVAL);
1445 if (own_uid == (uid_t)-1)
1446 return (EINVAL);
1447 if (own_gid == (gid_t)-1)
1448 return (EINVAL);
1449 #ifdef _KERNEL
1450 if ((acl_info->vsa_mask & VSA_ACE) == 0)
1451 return (EINVAL);
1452 zacecnt = acl_info->vsa_aclcnt;
1453 zacevec = acl_info->vsa_aclentp;
1454 #else /* _KERNEL */
1455 if (acl_info->acl_type != ACE_T ||
1456 acl_info->acl_entry_size != sizeof (ace_t))
1457 return (EINVAL);
1458 zacecnt = acl_info->acl_cnt;
1459 zacevec = acl_info->acl_aclp;
1460 #endif /* _KERNEL */
1461 if (zacecnt == 0 || zacevec == NULL)
1462 return (EINVAL);
1463 mapcnt += zacecnt;
1465 if (mapcnt == 0)
1466 return (EINVAL);
1467 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
1468 if (mapinfo == NULL)
1469 return (ENOMEM);
1470 bzero(mapinfo, mapcnt * sizeof (*mapinfo));
1471 /* no more returns until errout */
1474 * Get an imap "batch" request handle.
1476 #ifdef _KERNEL
1477 idmap_gh = kidmap_get_create(curproc->p_zone);
1478 #else /* _KERNEL */
1479 idms = idmap_get_create(&idmap_gh);
1480 if (idms != IDMAP_SUCCESS) {
1481 error = ENOTACTIVE;
1482 goto errout;
1484 #endif /* _KERNEL */
1487 * Build our request to the idmap deamon,
1488 * getting SIDs for every Unix UID/GID.
1489 * Also count DACL and SACL ACEs here.
1491 mip = mapinfo;
1492 if (selector & OWNER_SECURITY_INFORMATION) {
1493 error = mkrq_idmap_ux2sid(idmap_gh, mip,
1494 own_uid, IDM_TYPE_USER);
1495 if (error)
1496 goto errout;
1497 mip++;
1499 if (selector & GROUP_SECURITY_INFORMATION) {
1500 error = mkrq_idmap_ux2sid(idmap_gh, mip,
1501 own_gid, IDM_TYPE_GROUP);
1502 if (error)
1503 goto errout;
1504 mip++;
1506 if (selector & (DACL_SECURITY_INFORMATION |
1507 SACL_SECURITY_INFORMATION)) {
1508 int rqtype;
1509 uid_t uid;
1511 zacep = zacevec;
1512 for (i = 0; i < zacecnt; i++) {
1514 switch (zacep->a_type) {
1515 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1516 case ACE_ACCESS_DENIED_ACE_TYPE:
1517 dacl_acecnt++;
1518 break;
1519 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1520 case ACE_SYSTEM_ALARM_ACE_TYPE:
1521 sacl_acecnt++;
1522 break;
1523 /* other types todo */
1526 if (zacep->a_flags & ACE_EVERYONE) {
1527 rqtype = IDM_EVERYONE;
1528 uid = (uid_t)-1;
1529 } else if (zacep->a_flags & ACE_GROUP) {
1530 /* owning group (a_who = -1) */
1531 rqtype = IDM_TYPE_GROUP;
1532 uid = (uid_t)own_gid;
1533 } else if (zacep->a_flags & ACE_OWNER) {
1534 /* owning user (a_who = -1) */
1535 rqtype = IDM_TYPE_USER;
1536 uid = (uid_t)own_uid;
1537 } else if (zacep->a_flags & ACE_IDENTIFIER_GROUP) {
1538 /* regular group */
1539 rqtype = IDM_TYPE_GROUP;
1540 uid = zacep->a_who;
1541 } else {
1542 rqtype = IDM_TYPE_USER;
1543 uid = zacep->a_who;
1546 error = mkrq_idmap_ux2sid(idmap_gh, mip, uid, rqtype);
1547 if (error)
1548 goto errout;
1549 zacep++;
1550 mip++;
1554 idms = I_getmappings(idmap_gh);
1555 if (idms != IDMAP_SUCCESS) {
1556 /* creative error choice */
1557 error = EIDRM;
1558 goto errout;
1562 * With any luck, we now have a Windows SID for
1563 * every Unix UID or GID in the NFS/ZFS ACL.
1564 * The remaining work is just format conversion,
1565 * memory allocation, etc.
1567 if ((sd = MALLOC(sizeof (*sd))) == NULL) {
1568 error = ENOMEM;
1569 goto errout;
1571 bzero(sd, sizeof (*sd));
1572 sd->sd_revision = NT_SD_REVISION;
1574 mip = mapinfo;
1575 if (selector & OWNER_SECURITY_INFORMATION) {
1576 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1577 &sd->sd_owner);
1578 mip++;
1580 if (selector & GROUP_SECURITY_INFORMATION) {
1581 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1582 &sd->sd_group);
1583 mip++;
1587 * If setting both DACL and SACL, we will
1588 * make two passes starting here in mapinfo.
1590 mip_acl = mip;
1592 if (selector & DACL_SECURITY_INFORMATION) {
1594 * Caller wants to set the DACL.
1596 aclsz = I_ACL_SIZE(dacl_acecnt);
1597 if ((acl = MALLOC(aclsz)) == NULL) {
1598 error = ENOMEM;
1599 goto errout;
1601 bzero(acl, aclsz);
1603 acl->acl_revision = NT_ACL_REVISION;
1604 acl->acl_acecount = (uint16_t)dacl_acecnt;
1605 acep = &acl->acl_acevec[0];
1607 /* 1st pass - scan for DACL ACE types. */
1608 mip = mip_acl;
1609 zacep = zacevec;
1610 for (i = 0; i < zacecnt; i++) {
1612 switch (zacep->a_type) {
1613 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1614 case ACE_ACCESS_DENIED_ACE_TYPE:
1615 error = zace2ntace(acep, zacep, mip);
1616 if (error != 0)
1617 goto errout;
1618 acep++;
1619 break;
1621 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1622 case ACE_SYSTEM_ALARM_ACE_TYPE:
1623 break;
1624 /* other types todo */
1626 zacep++;
1627 mip++;
1629 sd->sd_dacl = acl;
1630 acl = NULL;
1631 sd->sd_flags |= SD_DACL_PRESENT;
1634 if (selector & SACL_SECURITY_INFORMATION) {
1636 * Caller wants to set the SACL.
1638 aclsz = I_ACL_SIZE(sacl_acecnt);
1639 if ((acl = MALLOC(aclsz)) == NULL) {
1640 error = ENOMEM;
1641 goto errout;
1643 bzero(acl, aclsz);
1645 acl->acl_revision = NT_ACL_REVISION;
1646 acl->acl_acecount = (uint16_t)sacl_acecnt;
1647 acep = &acl->acl_acevec[0];
1649 /* 2nd pass - scan for SACL ACE types. */
1650 mip = mip_acl;
1651 zacep = zacevec;
1652 for (i = 0; i < zacecnt; i++) {
1654 switch (zacep->a_type) {
1655 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1656 case ACE_ACCESS_DENIED_ACE_TYPE:
1657 break;
1659 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1660 case ACE_SYSTEM_ALARM_ACE_TYPE:
1661 error = zace2ntace(acep, zacep, mip);
1662 if (error != 0)
1663 goto errout;
1664 acep++;
1665 break;
1666 /* other types todo */
1668 zacep++;
1669 mip++;
1671 sd->sd_sacl = acl;
1672 acl = NULL;
1673 sd->sd_flags |= SD_SACL_PRESENT;
1676 *sdp = sd;
1677 error = 0;
1679 errout:
1680 if (error != 0) {
1681 if (acl != NULL)
1682 ifree_acl(acl);
1683 if (sd != NULL)
1684 smbfs_acl_free_sd(sd);
1686 if (mapinfo != NULL)
1687 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1688 #ifdef _KERNEL
1689 if (idmap_gh != NULL)
1690 kidmap_get_destroy(idmap_gh);
1691 #else /* _KERNEL */
1692 if (idmap_gh != NULL)
1693 idmap_get_destroy(idmap_gh);
1694 #endif /* _KERNEL */
1696 return (error);