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)
70 #define FREESZ(p, sz) free(p)
74 FREESZ(void *p
, size_t sz
)
81 #define ERRCHK(expr) if ((error = expr) != 0) goto errout
84 * Security IDentifier (SID)
87 ifree_sid(i_ntsid_t
*sid
)
94 sz
= I_SID_SIZE(sid
->sid_subauthcount
);
99 md_get_sid(mdchain_t
*mdp
, i_ntsid_t
**sidp
)
101 i_ntsid_t
*sid
= NULL
;
102 uint8_t revision
, subauthcount
;
107 if ((error
= md_get_uint8(mdp
, &revision
)) != 0)
109 if ((error
= md_get_uint8(mdp
, &subauthcount
)) != 0)
112 sidsz
= I_SID_SIZE(subauthcount
);
114 if ((sid
= MALLOC(sidsz
)) == NULL
)
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
));
138 mb_put_sid(mbchain_t
*mbp
, i_ntsid_t
*sid
)
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
));
165 * Access Control Entry (ACE)
168 ifree_ace(i_ntace_t
*ace
)
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
));
182 /* other types todo */
189 md_get_ace(mdchain_t
*mdp
, i_ntace_t
**acep
)
192 i_ntace_hdr_t ace_hdr
;
193 i_ntace_t
*ace
= NULL
;
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.
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
)
220 bzero(ace
, alloc_size
);
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
));
230 /* other types todo */
236 /* Now actually consume ace_hdr.ace_size */
237 ERRCHK(md_get_mem(mdp
, NULL
, ace_hdr
.ace_size
, MB_MSYSTEM
));
249 mb_put_ace(mbchain_t
*mbp
, i_ntace_t
*ace
)
252 uint16_t ace_len
, *ace_len_p
;
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
) {
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
));
281 /* other types todo */
287 /* Fill in the (OtW) ACE length. */
288 ace_len
= mbp
->mb_count
- cnt0
;
289 *ace_len_p
= htoles(ace_len
);
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 *))
307 ifree_acl(i_ntacl_t
*acl
)
316 acep
= &acl
->acl_acevec
[0];
317 for (i
= 0; i
< acl
->acl_acecount
; i
++) {
321 sz
= I_ACL_SIZE(acl
->acl_acecount
);
326 md_get_acl(mdchain_t
*mdp
, i_ntacl_t
**aclp
)
328 i_ntacl_t
*acl
= NULL
;
331 uint16_t acl_len
, acecount
;
335 if ((error
= md_get_uint8(mdp
, &revision
)) != 0)
337 if ((error
= md_get_uint8(mdp
, NULL
)) != 0) /* pad1 */
339 if ((error
= md_get_uint16le(mdp
, &acl_len
)) != 0)
341 if ((error
= md_get_uint16le(mdp
, &acecount
)) != 0)
343 if ((error
= md_get_uint16le(mdp
, NULL
)) != 0) /* pad2 */
346 aclsz
= I_ACL_SIZE(acecount
);
347 if ((acl
= MALLOC(aclsz
)) == NULL
)
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
));
359 * There may be more data here, but
360 * the caller takes care of that.
373 mb_put_acl(mbchain_t
*mbp
, i_ntacl_t
*acl
)
376 uint16_t acl_len
, *acl_len_p
;
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
) {
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
));
397 /* Fill in acl_len_p */
398 acl_len
= mbp
->mb_count
- cnt0
;
399 *acl_len_p
= htoles(acl_len
);
410 * Security Descriptor
413 smbfs_acl_free_sd(i_ntsd_t
*sd
)
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
)
439 mdchain_t top_md
, tmp_md
;
440 uint32_t owneroff
, groupoff
, sacloff
, dacloff
;
443 if ((sd
= MALLOC(sizeof (*sd
))) == NULL
)
445 bzero(sd
, sizeof (*sd
));
448 * Offsets below are relative to this point,
449 * so save the mdp state for use below.
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.
476 md_get_mem(&tmp_md
, NULL
, sacloff
, MB_MSYSTEM
);
477 ERRCHK(md_get_acl(&tmp_md
, &sd
->sd_sacl
));
481 md_get_mem(&tmp_md
, NULL
, dacloff
, MB_MSYSTEM
);
482 ERRCHK(md_get_acl(&tmp_md
, &sd
->sd_dacl
));
486 md_get_mem(&tmp_md
, NULL
, owneroff
, MB_MSYSTEM
);
487 ERRCHK(md_get_sid(&tmp_md
, &sd
->sd_owner
));
491 md_get_mem(&tmp_md
, NULL
, groupoff
, MB_MSYSTEM
);
492 ERRCHK(md_get_sid(&tmp_md
, &sd
->sd_group
));
500 smbfs_acl_free_sd(sd
);
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
;
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
) {
538 * These could be marshalled in any order, but
539 * are normally found in the order shown here.
542 sacloff
= mbp
->mb_count
- cnt0
;
543 ERRCHK(mb_put_acl(mbp
, sd
->sd_sacl
));
546 dacloff
= mbp
->mb_count
- cnt0
;
547 ERRCHK(mb_put_acl(mbp
, sd
->sd_dacl
));
550 owneroff
= mbp
->mb_count
- cnt0
;
551 ERRCHK(mb_put_sid(mbp
, sd
->sd_owner
));
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
);
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.
588 uint32_t gf_specific
;
590 static const struct 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
},
625 * Table for translating ZFS ACE flags to NT ACE flags.
626 * The low four bits are the same, but not others.
632 static const struct 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
},
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
)
662 n
= snprintf(s
, osz
, "S-%u", sid
->sid_revision
);
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
);
674 subs
= sid
->sid_subauthcount
;
675 if (subs
< 1 || subs
> 15)
680 ip
= &sid
->sid_subauthvec
[0];
681 for (; subs
; subs
--, ip
++) {
682 n
= snprintf(s
, osz
, "-%u", *ip
);
690 /* LINTED E_PTRDIFF_OVERFLOW */
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.
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
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
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
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)
760 idmap_get_handle_t
*idmap_gh
,
761 struct mapinfo2uid
*mip
,
770 if (smbfs_sid2str(sid
, strbuf
, sizeof (strbuf
), &rid
) < 0)
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
;
788 mip
->mi_isuser
= req_type
;
789 idms
= I_getuidbysid(idmap_gh
, sid_prefix
, rid
,
790 &mip
->mi_uid
, &mip
->mi_status
);
794 mip
->mi_isuser
= req_type
;
795 idms
= I_getgidbysid(idmap_gh
, sid_prefix
, rid
,
796 &mip
->mi_uid
, &mip
->mi_status
);
800 idms
= I_getpidbysid(idmap_gh
, sid_prefix
, rid
,
801 &mip
->mi_uid
, &mip
->mi_isuser
, &mip
->mi_status
);
805 idms
= IDMAP_ERR_OTHER
;
809 if (idms
!= IDMAP_SUCCESS
)
816 * Convert an NT ACE to a ZFS ACE.
817 * ACE type was already validated.
820 ntace2zace(ace_t
*zacep
, i_ntace_t
*ntace
, struct mapinfo2uid
*mip
)
822 const struct zaf2naf
*znaf
;
828 * Set the "ID type" flags in the ZFS ace flags.
831 switch (mip
->mi_isuser
) {
833 zflags
= ACE_EVERYONE
;
837 case IDM_TYPE_GROUP
: /* it's a GID */
838 zflags
= ACE_IDENTIFIER_GROUP
;
843 case IDM_TYPE_USER
: /* it's a UID */
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
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.
891 vsecattr_t
*acl_info
,
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;
904 idmap_get_handle_t
*idmap_gh
= NULL
;
912 if (acl_info
->acl_type
!= ACE_T
||
913 acl_info
->acl_aclp
!= NULL
||
914 acl_info
->acl_entry_size
!= sizeof (ace_t
))
917 if ((sd
->sd_flags
& SD_DACL_PRESENT
) == 0)
922 * How many SID mappings will we need?
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
;
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.
946 mapinfo
= MALLOC(mapcnt
* sizeof (*mapinfo
));
947 if (mapinfo
== NULL
) {
951 bzero(mapinfo
, mapcnt
* sizeof (*mapinfo
));
955 * Get an imap "batch" request handle.
958 idmap_gh
= kidmap_get_create(curproc
->p_zone
);
960 idms
= idmap_get_create(&idmap_gh
);
961 if (idms
!= IDMAP_SUCCESS
) {
968 * Build our request to the idmap deamon,
969 * getting Unix IDs for every SID.
973 error
= mkrq_idmap_sid2ux(idmap_gh
, mip
,
974 sd
->sd_owner
, IDM_TYPE_USER
);
980 error
= mkrq_idmap_sid2ux(idmap_gh
, mip
,
981 sd
->sd_group
, IDM_TYPE_GROUP
);
986 if ((sd
->sd_flags
& SD_SACL_PRESENT
) &&
987 (sd
->sd_sacl
!= NULL
)) {
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
);
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
);
1013 if (mip
!= mapinfo
) {
1014 idms
= I_getmappings(idmap_gh
);
1015 if (idms
!= IDMAP_SUCCESS
) {
1016 /* creative error choice */
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.
1029 own_uid
= mip
->mi_uid
;
1033 own_gid
= mip
->mi_uid
;
1042 if (acl_info
== NULL
) {
1043 /* Caller only wanted uid/gid */
1048 * Build the ZFS-style ACL
1049 * First, allocate the most ZFS ACEs we'll need.
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
;
1062 * DACL is NULL or empty. Either way,
1063 * we'll need to add a ZFS ACE below.
1067 zacl_size
= zacecnt
* sizeof (ace_t
);
1068 zacep0
= MALLOC(zacl_size
);
1069 if (zacep0
== NULL
) {
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
);
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
);
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
;
1121 acl_info
->vsa_aclcnt
= zacecnt
;
1122 acl_info
->vsa_aclentp
= zacep0
;
1123 acl_info
->vsa_aclentsz
= zacl_size
;
1125 acl_info
->acl_cnt
= zacecnt
;
1126 acl_info
->acl_aclp
= zacep0
;
1127 #endif /* _KERNEL */
1133 if (mapinfo
!= NULL
)
1134 FREESZ(mapinfo
, mapcnt
* sizeof (*mapinfo
));
1136 if (idmap_gh
!= NULL
)
1137 kidmap_get_destroy(idmap_gh
);
1139 if (idmap_gh
!= NULL
)
1140 idmap_get_destroy(idmap_gh
);
1141 #endif /* _KERNEL */
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;
1173 if (sid_prefix
== NULL
)
1177 if (strncmp(p
, "S-1-", 4) != 0)
1181 /* Parse the "authority" */
1183 err
= ddi_strtoull(p
, &np
, 10, &auth
);
1187 auth
= strtoull(p
, &np
, 10);
1190 #endif /* _KERNEL */
1193 * Count the sub-authorities. Here, np points to
1194 * the "-" before the first sub-authority.
1197 for (p
= np
; *p
; p
++) {
1204 /* Allocate the internal SID. */
1205 size
= I_SID_SIZE(sacnt
);
1212 sid
->sid_revision
= 1;
1213 sid
->sid_subauthcount
= sacnt
;
1214 for (i
= 5; i
>= 0; i
--) {
1215 sid
->sid_authority
[i
] = auth
& 0xFF;
1221 sacnt
--; /* Last SA not from string */
1223 for (i
= 0; i
< sacnt
; i
++) {
1230 err
= ddi_strtoul(p
, &np
, 10, &sa
);
1234 sa
= strtoul(p
, &np
, 10);
1239 #endif /* _KERNEL */
1240 sid
->sid_subauthvec
[i
] = (uint32_t)sa
;
1246 sid
->sid_subauthvec
[i
] = *ridp
;
1259 * The idmap API is _almost_ the same between
1260 * kernel and user-level. But not quite...
1261 * Hope this improves readability below.
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)
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. */
1284 const char *mi_dsid
; /* domain SID */
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)
1298 idmap_get_handle_t
*idmap_gh
,
1299 struct mapinfo2sid
*mip
,
1300 uid_t uid
, /* or gid */
1308 if (uid
== (uid_t
)-1)
1310 idms
= I_getsidbyuid(idmap_gh
, uid
,
1311 &mip
->mi_dsid
, &mip
->mi_rid
, &mip
->mi_status
);
1314 case IDM_TYPE_GROUP
:
1315 if (uid
== (uid_t
)-1)
1317 idms
= I_getsidbygid(idmap_gh
, uid
,
1318 &mip
->mi_dsid
, &mip
->mi_rid
, &mip
->mi_status
);
1322 mip
->mi_dsid
= "S-1-1";
1325 idms
= IDMAP_SUCCESS
;
1329 idms
= IDMAP_ERR_OTHER
;
1333 if (idms
!= IDMAP_SUCCESS
)
1340 * Convert a ZFS ACE to an NT ACE.
1341 * ACE type was already validated.
1344 zace2ntace(i_ntace_t
**ntacep
, ace_t
*zacep
, struct mapinfo2sid
*mip
)
1346 const struct zaf2naf
*znaf
;
1348 uint16_t alloc_size
;
1350 i_ntace_t
*ntace
= NULL
;
1351 i_ntsid_t
*sid
= NULL
;
1354 if (mip
->mi_dsid
== NULL
|| mip
->mi_status
!= 0) {
1359 * Translate ZFS ACE flags to NT ACE flags.
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
);
1380 * Allocate the NT ACE and fill it in.
1382 alloc_size
= sizeof (i_ntace_v2_t
);
1383 if ((ntace
= MALLOC(alloc_size
)) == NULL
) {
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
;
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.
1413 vsecattr_t
*acl_info
,
1416 #endif /* _KERNEL */
1422 struct mapinfo2sid
*mip
, *mip_acl
, *mapinfo
= NULL
;
1423 int aclsz
, error
, i
, mapcnt
;
1424 int dacl_acecnt
= 0;
1425 int sacl_acecnt
= 0;
1427 ace_t
*zacevec
= NULL
;
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
;
1436 * First, get all the UID+GID to SID mappings.
1437 * How many? Also sanity checks.
1440 if (selector
& OWNER_SECURITY_INFORMATION
) {
1441 if (own_uid
== (uid_t
)-1)
1445 if (selector
& GROUP_SECURITY_INFORMATION
) {
1446 if (own_gid
== (gid_t
)-1)
1450 if (selector
& (DACL_SECURITY_INFORMATION
|
1451 SACL_SECURITY_INFORMATION
)) {
1452 if (acl_info
== NULL
)
1454 if (own_uid
== (uid_t
)-1)
1456 if (own_gid
== (gid_t
)-1)
1459 if ((acl_info
->vsa_mask
& VSA_ACE
) == 0)
1461 zacecnt
= acl_info
->vsa_aclcnt
;
1462 zacevec
= acl_info
->vsa_aclentp
;
1464 if (acl_info
->acl_type
!= ACE_T
||
1465 acl_info
->acl_entry_size
!= sizeof (ace_t
))
1467 zacecnt
= acl_info
->acl_cnt
;
1468 zacevec
= acl_info
->acl_aclp
;
1469 #endif /* _KERNEL */
1470 if (zacecnt
== 0 || zacevec
== NULL
)
1476 mapinfo
= MALLOC(mapcnt
* sizeof (*mapinfo
));
1477 if (mapinfo
== NULL
)
1479 bzero(mapinfo
, mapcnt
* sizeof (*mapinfo
));
1480 /* no more returns until errout */
1483 * Get an imap "batch" request handle.
1486 idmap_gh
= kidmap_get_create(curproc
->p_zone
);
1488 idms
= idmap_get_create(&idmap_gh
);
1489 if (idms
!= IDMAP_SUCCESS
) {
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.
1501 if (selector
& OWNER_SECURITY_INFORMATION
) {
1502 error
= mkrq_idmap_ux2sid(idmap_gh
, mip
,
1503 own_uid
, IDM_TYPE_USER
);
1508 if (selector
& GROUP_SECURITY_INFORMATION
) {
1509 error
= mkrq_idmap_ux2sid(idmap_gh
, mip
,
1510 own_gid
, IDM_TYPE_GROUP
);
1515 if (selector
& (DACL_SECURITY_INFORMATION
|
1516 SACL_SECURITY_INFORMATION
)) {
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
:
1528 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
1529 case ACE_SYSTEM_ALARM_ACE_TYPE
:
1532 /* other types todo */
1535 if (zacep
->a_flags
& ACE_EVERYONE
) {
1536 rqtype
= IDM_EVERYONE
;
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
) {
1548 rqtype
= IDM_TYPE_GROUP
;
1551 rqtype
= IDM_TYPE_USER
;
1555 error
= mkrq_idmap_ux2sid(idmap_gh
, mip
, uid
, rqtype
);
1563 idms
= I_getmappings(idmap_gh
);
1564 if (idms
!= IDMAP_SUCCESS
) {
1565 /* creative error choice */
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
) {
1580 bzero(sd
, sizeof (*sd
));
1581 sd
->sd_revision
= NT_SD_REVISION
;
1584 if (selector
& OWNER_SECURITY_INFORMATION
) {
1585 error
= smbfs_str2sid(mip
->mi_dsid
, &mip
->mi_rid
,
1589 if (selector
& GROUP_SECURITY_INFORMATION
) {
1590 error
= smbfs_str2sid(mip
->mi_dsid
, &mip
->mi_rid
,
1596 * If setting both DACL and SACL, we will
1597 * make two passes starting here in mapinfo.
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
) {
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. */
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
);
1630 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
1631 case ACE_SYSTEM_ALARM_ACE_TYPE
:
1633 /* other types todo */
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
) {
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. */
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
:
1668 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
1669 case ACE_SYSTEM_ALARM_ACE_TYPE
:
1670 error
= zace2ntace(acep
, zacep
, mip
);
1675 /* other types todo */
1682 sd
->sd_flags
|= SD_SACL_PRESENT
;
1693 smbfs_acl_free_sd(sd
);
1695 if (mapinfo
!= NULL
)
1696 FREESZ(mapinfo
, mapcnt
* sizeof (*mapinfo
));
1698 if (idmap_gh
!= NULL
)
1699 kidmap_get_destroy(idmap_gh
);
1701 if (idmap_gh
!= NULL
)
1702 idmap_get_destroy(idmap_gh
);
1703 #endif /* _KERNEL */