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]
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>
34 #include <sys/byteorder.h>
39 #include <sys/cmn_err.h>
41 #include <sys/sunddi.h>
42 #include <sys/vnode.h>
45 #include <sys/kidmap.h>
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
65 #define MALLOC(size) kmem_alloc(size, KM_SLEEP)
66 #define FREESZ(p, sz) kmem_free(p, sz)
68 #define MALLOC(size) malloc(size)
69 #define FREESZ(p, sz) free(p)
72 #define ERRCHK(expr) if ((error = expr) != 0) goto errout
75 * Security IDentifier (SID)
78 ifree_sid(i_ntsid_t
*sid
)
85 sz
= I_SID_SIZE(sid
->sid_subauthcount
);
90 md_get_sid(mdchain_t
*mdp
, i_ntsid_t
**sidp
)
92 i_ntsid_t
*sid
= NULL
;
93 uint8_t revision
, subauthcount
;
98 if ((error
= md_get_uint8(mdp
, &revision
)) != 0)
100 if ((error
= md_get_uint8(mdp
, &subauthcount
)) != 0)
103 sidsz
= I_SID_SIZE(subauthcount
);
105 if ((sid
= MALLOC(sidsz
)) == NULL
)
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
));
129 mb_put_sid(mbchain_t
*mbp
, i_ntsid_t
*sid
)
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
));
156 * Access Control Entry (ACE)
159 ifree_ace(i_ntace_t
*ace
)
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
));
173 /* other types todo */
180 md_get_ace(mdchain_t
*mdp
, i_ntace_t
**acep
)
183 i_ntace_hdr_t ace_hdr
;
184 i_ntace_t
*ace
= NULL
;
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.
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
)
211 bzero(ace
, alloc_size
);
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
));
221 /* other types todo */
227 /* Now actually consume ace_hdr.ace_size */
228 ERRCHK(md_get_mem(mdp
, NULL
, ace_hdr
.ace_size
, MB_MSYSTEM
));
240 mb_put_ace(mbchain_t
*mbp
, i_ntace_t
*ace
)
243 uint16_t ace_len
, *ace_len_p
;
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
) {
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
));
272 /* other types todo */
278 /* Fill in the (OtW) ACE length. */
279 ace_len
= mbp
->mb_count
- cnt0
;
280 *ace_len_p
= htoles(ace_len
);
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 *))
298 ifree_acl(i_ntacl_t
*acl
)
307 acep
= &acl
->acl_acevec
[0];
308 for (i
= 0; i
< acl
->acl_acecount
; i
++) {
312 sz
= I_ACL_SIZE(acl
->acl_acecount
);
317 md_get_acl(mdchain_t
*mdp
, i_ntacl_t
**aclp
)
319 i_ntacl_t
*acl
= NULL
;
322 uint16_t acl_len
, acecount
;
326 if ((error
= md_get_uint8(mdp
, &revision
)) != 0)
328 if ((error
= md_get_uint8(mdp
, NULL
)) != 0) /* pad1 */
330 if ((error
= md_get_uint16le(mdp
, &acl_len
)) != 0)
332 if ((error
= md_get_uint16le(mdp
, &acecount
)) != 0)
334 if ((error
= md_get_uint16le(mdp
, NULL
)) != 0) /* pad2 */
337 aclsz
= I_ACL_SIZE(acecount
);
338 if ((acl
= MALLOC(aclsz
)) == NULL
)
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
));
350 * There may be more data here, but
351 * the caller takes care of that.
364 mb_put_acl(mbchain_t
*mbp
, i_ntacl_t
*acl
)
367 uint16_t acl_len
, *acl_len_p
;
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
) {
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
));
388 /* Fill in acl_len_p */
389 acl_len
= mbp
->mb_count
- cnt0
;
390 *acl_len_p
= htoles(acl_len
);
401 * Security Descriptor
404 smbfs_acl_free_sd(i_ntsd_t
*sd
)
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
)
430 mdchain_t top_md
, tmp_md
;
431 uint32_t owneroff
, groupoff
, sacloff
, dacloff
;
434 if ((sd
= MALLOC(sizeof (*sd
))) == NULL
)
436 bzero(sd
, sizeof (*sd
));
439 * Offsets below are relative to this point,
440 * so save the mdp state for use below.
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.
467 md_get_mem(&tmp_md
, NULL
, sacloff
, MB_MSYSTEM
);
468 ERRCHK(md_get_acl(&tmp_md
, &sd
->sd_sacl
));
472 md_get_mem(&tmp_md
, NULL
, dacloff
, MB_MSYSTEM
);
473 ERRCHK(md_get_acl(&tmp_md
, &sd
->sd_dacl
));
477 md_get_mem(&tmp_md
, NULL
, owneroff
, MB_MSYSTEM
);
478 ERRCHK(md_get_sid(&tmp_md
, &sd
->sd_owner
));
482 md_get_mem(&tmp_md
, NULL
, groupoff
, MB_MSYSTEM
);
483 ERRCHK(md_get_sid(&tmp_md
, &sd
->sd_group
));
491 smbfs_acl_free_sd(sd
);
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
;
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
) {
529 * These could be marshalled in any order, but
530 * are normally found in the order shown here.
533 sacloff
= mbp
->mb_count
- cnt0
;
534 ERRCHK(mb_put_acl(mbp
, sd
->sd_sacl
));
537 dacloff
= mbp
->mb_count
- cnt0
;
538 ERRCHK(mb_put_acl(mbp
, sd
->sd_dacl
));
541 owneroff
= mbp
->mb_count
- cnt0
;
542 ERRCHK(mb_put_sid(mbp
, sd
->sd_owner
));
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
);
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.
579 uint32_t gf_specific
;
581 static const struct 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
},
616 * Table for translating ZFS ACE flags to NT ACE flags.
617 * The low four bits are the same, but not others.
623 static const struct 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
},
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
)
653 n
= snprintf(s
, osz
, "S-%u", sid
->sid_revision
);
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
);
665 subs
= sid
->sid_subauthcount
;
666 if (subs
< 1 || subs
> 15)
671 ip
= &sid
->sid_subauthvec
[0];
672 for (; subs
; subs
--, ip
++) {
673 n
= snprintf(s
, osz
, "-%u", *ip
);
681 /* LINTED E_PTRDIFF_OVERFLOW */
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.
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
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
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
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)
751 idmap_get_handle_t
*idmap_gh
,
752 struct mapinfo2uid
*mip
,
761 if (smbfs_sid2str(sid
, strbuf
, sizeof (strbuf
), &rid
) < 0)
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
;
779 mip
->mi_isuser
= req_type
;
780 idms
= I_getuidbysid(idmap_gh
, sid_prefix
, rid
,
781 &mip
->mi_uid
, &mip
->mi_status
);
785 mip
->mi_isuser
= req_type
;
786 idms
= I_getgidbysid(idmap_gh
, sid_prefix
, rid
,
787 &mip
->mi_uid
, &mip
->mi_status
);
791 idms
= I_getpidbysid(idmap_gh
, sid_prefix
, rid
,
792 &mip
->mi_uid
, &mip
->mi_isuser
, &mip
->mi_status
);
796 idms
= IDMAP_ERR_OTHER
;
800 if (idms
!= IDMAP_SUCCESS
)
807 * Convert an NT ACE to a ZFS ACE.
808 * ACE type was already validated.
811 ntace2zace(ace_t
*zacep
, i_ntace_t
*ntace
, struct mapinfo2uid
*mip
)
813 const struct zaf2naf
*znaf
;
819 * Set the "ID type" flags in the ZFS ace flags.
822 switch (mip
->mi_isuser
) {
824 zflags
= ACE_EVERYONE
;
828 case IDM_TYPE_GROUP
: /* it's a GID */
829 zflags
= ACE_IDENTIFIER_GROUP
;
834 case IDM_TYPE_USER
: /* it's a UID */
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
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.
882 vsecattr_t
*acl_info
,
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;
895 idmap_get_handle_t
*idmap_gh
= NULL
;
903 if (acl_info
->acl_type
!= ACE_T
||
904 acl_info
->acl_aclp
!= NULL
||
905 acl_info
->acl_entry_size
!= sizeof (ace_t
))
908 if ((sd
->sd_flags
& SD_DACL_PRESENT
) == 0)
913 * How many SID mappings will we need?
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
;
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.
937 mapinfo
= MALLOC(mapcnt
* sizeof (*mapinfo
));
938 if (mapinfo
== NULL
) {
942 bzero(mapinfo
, mapcnt
* sizeof (*mapinfo
));
946 * Get an imap "batch" request handle.
949 idmap_gh
= kidmap_get_create(curproc
->p_zone
);
951 idms
= idmap_get_create(&idmap_gh
);
952 if (idms
!= IDMAP_SUCCESS
) {
959 * Build our request to the idmap deamon,
960 * getting Unix IDs for every SID.
964 error
= mkrq_idmap_sid2ux(idmap_gh
, mip
,
965 sd
->sd_owner
, IDM_TYPE_USER
);
971 error
= mkrq_idmap_sid2ux(idmap_gh
, mip
,
972 sd
->sd_group
, IDM_TYPE_GROUP
);
977 if ((sd
->sd_flags
& SD_SACL_PRESENT
) &&
978 (sd
->sd_sacl
!= NULL
)) {
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
);
990 if ((sd
->sd_flags
& SD_DACL_PRESENT
) &&
991 (sd
->sd_dacl
!= NULL
)) {
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
);
1004 if (mip
!= mapinfo
) {
1005 idms
= I_getmappings(idmap_gh
);
1006 if (idms
!= IDMAP_SUCCESS
) {
1007 /* creative error choice */
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.
1020 own_uid
= mip
->mi_uid
;
1024 own_gid
= mip
->mi_uid
;
1033 if (acl_info
== NULL
) {
1034 /* Caller only wanted uid/gid */
1039 * Build the ZFS-style ACL
1040 * First, allocate the most ZFS ACEs we'll need.
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
;
1053 * DACL is NULL or empty. Either way,
1054 * we'll need to add a ZFS ACE below.
1058 zacl_size
= zacecnt
* sizeof (ace_t
);
1059 zacep0
= MALLOC(zacl_size
);
1060 if (zacep0
== NULL
) {
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
);
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
);
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
;
1112 acl_info
->vsa_aclcnt
= zacecnt
;
1113 acl_info
->vsa_aclentp
= zacep0
;
1114 acl_info
->vsa_aclentsz
= zacl_size
;
1116 acl_info
->acl_cnt
= zacecnt
;
1117 acl_info
->acl_aclp
= zacep0
;
1118 #endif /* _KERNEL */
1124 if (mapinfo
!= NULL
)
1125 FREESZ(mapinfo
, mapcnt
* sizeof (*mapinfo
));
1127 if (idmap_gh
!= NULL
)
1128 kidmap_get_destroy(idmap_gh
);
1130 if (idmap_gh
!= NULL
)
1131 idmap_get_destroy(idmap_gh
);
1132 #endif /* _KERNEL */
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;
1164 if (sid_prefix
== NULL
)
1168 if (strncmp(p
, "S-1-", 4) != 0)
1172 /* Parse the "authority" */
1174 err
= ddi_strtoull(p
, &np
, 10, &auth
);
1178 auth
= strtoull(p
, &np
, 10);
1181 #endif /* _KERNEL */
1184 * Count the sub-authorities. Here, np points to
1185 * the "-" before the first sub-authority.
1188 for (p
= np
; *p
; p
++) {
1195 /* Allocate the internal SID. */
1196 size
= I_SID_SIZE(sacnt
);
1203 sid
->sid_revision
= 1;
1204 sid
->sid_subauthcount
= sacnt
;
1205 for (i
= 5; i
>= 0; i
--) {
1206 sid
->sid_authority
[i
] = auth
& 0xFF;
1212 sacnt
--; /* Last SA not from string */
1214 for (i
= 0; i
< sacnt
; i
++) {
1221 err
= ddi_strtoul(p
, &np
, 10, &sa
);
1225 sa
= strtoul(p
, &np
, 10);
1230 #endif /* _KERNEL */
1231 sid
->sid_subauthvec
[i
] = (uint32_t)sa
;
1237 sid
->sid_subauthvec
[i
] = *ridp
;
1250 * The idmap API is _almost_ the same between
1251 * kernel and user-level. But not quite...
1252 * Hope this improves readability below.
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)
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. */
1275 const char *mi_dsid
; /* domain SID */
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)
1289 idmap_get_handle_t
*idmap_gh
,
1290 struct mapinfo2sid
*mip
,
1291 uid_t uid
, /* or gid */
1299 if (uid
== (uid_t
)-1)
1301 idms
= I_getsidbyuid(idmap_gh
, uid
,
1302 &mip
->mi_dsid
, &mip
->mi_rid
, &mip
->mi_status
);
1305 case IDM_TYPE_GROUP
:
1306 if (uid
== (uid_t
)-1)
1308 idms
= I_getsidbygid(idmap_gh
, uid
,
1309 &mip
->mi_dsid
, &mip
->mi_rid
, &mip
->mi_status
);
1313 mip
->mi_dsid
= "S-1-1";
1316 idms
= IDMAP_SUCCESS
;
1320 idms
= IDMAP_ERR_OTHER
;
1324 if (idms
!= IDMAP_SUCCESS
)
1331 * Convert a ZFS ACE to an NT ACE.
1332 * ACE type was already validated.
1335 zace2ntace(i_ntace_t
**ntacep
, ace_t
*zacep
, struct mapinfo2sid
*mip
)
1337 const struct zaf2naf
*znaf
;
1339 uint16_t alloc_size
;
1341 i_ntace_t
*ntace
= NULL
;
1342 i_ntsid_t
*sid
= NULL
;
1345 if (mip
->mi_dsid
== NULL
|| mip
->mi_status
!= 0) {
1350 * Translate ZFS ACE flags to NT ACE flags.
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
);
1371 * Allocate the NT ACE and fill it in.
1373 alloc_size
= sizeof (i_ntace_v2_t
);
1374 if ((ntace
= MALLOC(alloc_size
)) == NULL
) {
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
;
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.
1404 vsecattr_t
*acl_info
,
1407 #endif /* _KERNEL */
1413 struct mapinfo2sid
*mip
, *mip_acl
, *mapinfo
= NULL
;
1414 int aclsz
, error
, i
, mapcnt
;
1415 int dacl_acecnt
= 0;
1416 int sacl_acecnt
= 0;
1418 ace_t
*zacevec
= NULL
;
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
;
1427 * First, get all the UID+GID to SID mappings.
1428 * How many? Also sanity checks.
1431 if (selector
& OWNER_SECURITY_INFORMATION
) {
1432 if (own_uid
== (uid_t
)-1)
1436 if (selector
& GROUP_SECURITY_INFORMATION
) {
1437 if (own_gid
== (gid_t
)-1)
1441 if (selector
& (DACL_SECURITY_INFORMATION
|
1442 SACL_SECURITY_INFORMATION
)) {
1443 if (acl_info
== NULL
)
1445 if (own_uid
== (uid_t
)-1)
1447 if (own_gid
== (gid_t
)-1)
1450 if ((acl_info
->vsa_mask
& VSA_ACE
) == 0)
1452 zacecnt
= acl_info
->vsa_aclcnt
;
1453 zacevec
= acl_info
->vsa_aclentp
;
1455 if (acl_info
->acl_type
!= ACE_T
||
1456 acl_info
->acl_entry_size
!= sizeof (ace_t
))
1458 zacecnt
= acl_info
->acl_cnt
;
1459 zacevec
= acl_info
->acl_aclp
;
1460 #endif /* _KERNEL */
1461 if (zacecnt
== 0 || zacevec
== NULL
)
1467 mapinfo
= MALLOC(mapcnt
* sizeof (*mapinfo
));
1468 if (mapinfo
== NULL
)
1470 bzero(mapinfo
, mapcnt
* sizeof (*mapinfo
));
1471 /* no more returns until errout */
1474 * Get an imap "batch" request handle.
1477 idmap_gh
= kidmap_get_create(curproc
->p_zone
);
1479 idms
= idmap_get_create(&idmap_gh
);
1480 if (idms
!= IDMAP_SUCCESS
) {
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.
1492 if (selector
& OWNER_SECURITY_INFORMATION
) {
1493 error
= mkrq_idmap_ux2sid(idmap_gh
, mip
,
1494 own_uid
, IDM_TYPE_USER
);
1499 if (selector
& GROUP_SECURITY_INFORMATION
) {
1500 error
= mkrq_idmap_ux2sid(idmap_gh
, mip
,
1501 own_gid
, IDM_TYPE_GROUP
);
1506 if (selector
& (DACL_SECURITY_INFORMATION
|
1507 SACL_SECURITY_INFORMATION
)) {
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
:
1519 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
1520 case ACE_SYSTEM_ALARM_ACE_TYPE
:
1523 /* other types todo */
1526 if (zacep
->a_flags
& ACE_EVERYONE
) {
1527 rqtype
= IDM_EVERYONE
;
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
) {
1539 rqtype
= IDM_TYPE_GROUP
;
1542 rqtype
= IDM_TYPE_USER
;
1546 error
= mkrq_idmap_ux2sid(idmap_gh
, mip
, uid
, rqtype
);
1554 idms
= I_getmappings(idmap_gh
);
1555 if (idms
!= IDMAP_SUCCESS
) {
1556 /* creative error choice */
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
) {
1571 bzero(sd
, sizeof (*sd
));
1572 sd
->sd_revision
= NT_SD_REVISION
;
1575 if (selector
& OWNER_SECURITY_INFORMATION
) {
1576 error
= smbfs_str2sid(mip
->mi_dsid
, &mip
->mi_rid
,
1580 if (selector
& GROUP_SECURITY_INFORMATION
) {
1581 error
= smbfs_str2sid(mip
->mi_dsid
, &mip
->mi_rid
,
1587 * If setting both DACL and SACL, we will
1588 * make two passes starting here in mapinfo.
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
) {
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. */
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
);
1621 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
1622 case ACE_SYSTEM_ALARM_ACE_TYPE
:
1624 /* other types todo */
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
) {
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. */
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
:
1659 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
1660 case ACE_SYSTEM_ALARM_ACE_TYPE
:
1661 error
= zace2ntace(acep
, zacep
, mip
);
1666 /* other types todo */
1673 sd
->sd_flags
|= SD_SACL_PRESENT
;
1684 smbfs_acl_free_sd(sd
);
1686 if (mapinfo
!= NULL
)
1687 FREESZ(mapinfo
, mapcnt
* sizeof (*mapinfo
));
1689 if (idmap_gh
!= NULL
)
1690 kidmap_get_destroy(idmap_gh
);
1692 if (idmap_gh
!= NULL
)
1693 idmap_get_destroy(idmap_gh
);
1694 #endif /* _KERNEL */