1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21da6c28aaSamw /*
22f96bd5c8SAlan Wright * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23da6c28aaSamw * Use is subject to license terms.
24*7206bf49SGordon Ross *
25*7206bf49SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
26da6c28aaSamw */
27da6c28aaSamw
289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <sys/sid.h>
29da6c28aaSamw #include <sys/acl.h>
3055bf511dSas200622 #include <acl/acl_common.h>
316537f381Sas200622 #include <smbsrv/smb_sid.h>
32da6c28aaSamw #include <smbsrv/smb_fsops.h>
33da6c28aaSamw #include <smbsrv/smb_idmap.h>
3455bf511dSas200622 #include <smbsrv/smb_kproto.h>
35da6c28aaSamw
36da6c28aaSamw #define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE)
37da6c28aaSamw
38da6c28aaSamw #define ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER)
39da6c28aaSamw #define ZACE_IS_OWNGRP(zace) \
40da6c28aaSamw ((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP))
41da6c28aaSamw
42da6c28aaSamw #define ZACE_IS_USER(zace) \
43da6c28aaSamw (((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace)))
44da6c28aaSamw #define ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP)
45da6c28aaSamw #define ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE)
46da6c28aaSamw
47da6c28aaSamw #define ZACE_IS_PROPAGATE(zace) \
48da6c28aaSamw ((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0)
49da6c28aaSamw
50da6c28aaSamw #define ZACE_IS_CREATOR_OWNER(zace) \
51da6c28aaSamw (ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID))
52da6c28aaSamw
53da6c28aaSamw #define ZACE_IS_CREATOR_GROUP(zace) \
54da6c28aaSamw (ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID))
55da6c28aaSamw
56da6c28aaSamw #define ZACE_IS_CREATOR(zace) \
57da6c28aaSamw (ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace))
58da6c28aaSamw
59da6c28aaSamw /*
60da6c28aaSamw * ACE groups within a DACL
61da6c28aaSamw *
62da6c28aaSamw * This is from lower to higher ACE order priority
63da6c28aaSamw */
64da6c28aaSamw #define SMB_AG_START 0
65da6c28aaSamw #define SMB_AG_ALW_INHRT 0
66da6c28aaSamw #define SMB_AG_DNY_INHRT 1
67da6c28aaSamw #define SMB_AG_ALW_DRCT 2
68da6c28aaSamw #define SMB_AG_DNY_DRCT 3
69da6c28aaSamw #define SMB_AG_NUM 4
70da6c28aaSamw
7155bf511dSas200622 #define DEFAULT_DACL_ACENUM 2
7255bf511dSas200622 /*
7355bf511dSas200622 * Default ACL:
7455bf511dSas200622 * owner: full access
7555bf511dSas200622 * SYSTEM: full access
7655bf511dSas200622 */
77*7206bf49SGordon Ross #ifdef _KERNEL
78ae240eb8SGordon Ross static const ace_t const default_dacl[DEFAULT_DACL_ACENUM] = {
7955bf511dSas200622 { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
8055bf511dSas200622 { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
8155bf511dSas200622 ACE_ACCESS_ALLOWED_ACE_TYPE }
8255bf511dSas200622 };
83*7206bf49SGordon Ross #endif /* _KERNEL */
8455bf511dSas200622
8555bf511dSas200622 /*
8655bf511dSas200622 * Note:
87da6c28aaSamw *
8855bf511dSas200622 * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format
8955bf511dSas200622 * smb_fsacl_xxx functions work with acl_t which represents the Solaris native
9055bf511dSas200622 * format
9155bf511dSas200622 */
9255bf511dSas200622
93f96bd5c8SAlan Wright static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *);
94c8ec8eeaSjose borrego static acl_t *smb_fsacl_null_empty(boolean_t);
95*7206bf49SGordon Ross #ifdef _KERNEL
9655bf511dSas200622 static int smb_fsacl_inheritable(acl_t *, int);
979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_ace_inherit(ace_t *, ace_t *, int, uid_t, gid_t);
98*7206bf49SGordon Ross #endif /* _KERNEL */
99*7206bf49SGordon Ross
10055bf511dSas200622 static boolean_t smb_ace_isvalid(smb_ace_t *, int);
10155bf511dSas200622 static uint16_t smb_ace_len(smb_ace_t *);
10255bf511dSas200622 static uint32_t smb_ace_mask_g2s(uint32_t);
103c8ec8eeaSjose borrego static uint16_t smb_ace_flags_tozfs(uint8_t);
10455bf511dSas200622 static uint8_t smb_ace_flags_fromzfs(uint16_t);
105f96bd5c8SAlan Wright static boolean_t smb_ace_wellknown_update(const char *, ace_t *);
10655bf511dSas200622
10755bf511dSas200622 smb_acl_t *
smb_acl_alloc(uint8_t revision,uint16_t bsize,uint16_t acecnt)10855bf511dSas200622 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt)
10955bf511dSas200622 {
11055bf511dSas200622 smb_acl_t *acl;
11155bf511dSas200622 int size;
11255bf511dSas200622
11355bf511dSas200622 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t));
11455bf511dSas200622 acl = kmem_zalloc(size, KM_SLEEP);
11555bf511dSas200622 acl->sl_revision = revision;
11655bf511dSas200622 acl->sl_bsize = bsize;
11755bf511dSas200622 acl->sl_acecnt = acecnt;
11855bf511dSas200622 acl->sl_aces = (smb_ace_t *)(acl + 1);
11955bf511dSas200622
12055bf511dSas200622 list_create(&acl->sl_sorted, sizeof (smb_ace_t),
12155bf511dSas200622 offsetof(smb_ace_t, se_sln));
12255bf511dSas200622 return (acl);
12355bf511dSas200622 }
12455bf511dSas200622
12555bf511dSas200622 void
smb_acl_free(smb_acl_t * acl)12655bf511dSas200622 smb_acl_free(smb_acl_t *acl)
12755bf511dSas200622 {
12855bf511dSas200622 int i, size;
12955bf511dSas200622 void *ace;
13055bf511dSas200622
13155bf511dSas200622 if (acl == NULL)
13255bf511dSas200622 return;
13355bf511dSas200622
1346537f381Sas200622 for (i = 0; i < acl->sl_acecnt; i++)
1356537f381Sas200622 smb_sid_free(acl->sl_aces[i].se_sid);
13655bf511dSas200622
13755bf511dSas200622 while ((ace = list_head(&acl->sl_sorted)) != NULL)
13855bf511dSas200622 list_remove(&acl->sl_sorted, ace);
13955bf511dSas200622 list_destroy(&acl->sl_sorted);
14055bf511dSas200622
14155bf511dSas200622 size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t));
14255bf511dSas200622 kmem_free(acl, size);
14355bf511dSas200622 }
14455bf511dSas200622
14555bf511dSas200622 /*
14655bf511dSas200622 * smb_acl_len
14755bf511dSas200622 *
14855bf511dSas200622 * Returns the size of given ACL in bytes. Note that this
14955bf511dSas200622 * is not an in-memory size, it's the ACL's size as it would
15055bf511dSas200622 * appear on the wire
15155bf511dSas200622 */
15255bf511dSas200622 uint16_t
smb_acl_len(smb_acl_t * acl)15355bf511dSas200622 smb_acl_len(smb_acl_t *acl)
15455bf511dSas200622 {
155c8ec8eeaSjose borrego return ((acl) ? acl->sl_bsize : 0);
15655bf511dSas200622 }
15755bf511dSas200622
15855bf511dSas200622 boolean_t
smb_acl_isvalid(smb_acl_t * acl,int which_acl)15955bf511dSas200622 smb_acl_isvalid(smb_acl_t *acl, int which_acl)
16055bf511dSas200622 {
16155bf511dSas200622 int i;
16255bf511dSas200622
16355bf511dSas200622 if (acl->sl_bsize < SMB_ACL_HDRSIZE)
16455bf511dSas200622 return (B_FALSE);
16555bf511dSas200622
16655bf511dSas200622 if (acl->sl_revision != ACL_REVISION) {
16755bf511dSas200622 /*
16855bf511dSas200622 * we are rejecting ACLs with object-specific ACEs for now
16955bf511dSas200622 */
17055bf511dSas200622 return (B_FALSE);
17155bf511dSas200622 }
17255bf511dSas200622
17355bf511dSas200622 for (i = 0; i < acl->sl_acecnt; i++) {
17455bf511dSas200622 if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl))
17555bf511dSas200622 return (B_FALSE);
17655bf511dSas200622 }
17755bf511dSas200622
17855bf511dSas200622 return (B_TRUE);
17955bf511dSas200622 }
18055bf511dSas200622
18155bf511dSas200622 /*
18255bf511dSas200622 * smb_acl_sort
18355bf511dSas200622 *
18455bf511dSas200622 * Sorts the given ACL in place if it needs to be sorted.
185da6c28aaSamw *
186da6c28aaSamw * The following is an excerpt from MSDN website.
187da6c28aaSamw *
188da6c28aaSamw * Order of ACEs in a DACL
189da6c28aaSamw *
190da6c28aaSamw * For Windows NT versions 4.0 and earlier, the preferred order of ACEs
191da6c28aaSamw * is simple: In a DACL, all access-denied ACEs should precede any
192da6c28aaSamw * access-allowed ACEs.
193da6c28aaSamw *
194da6c28aaSamw * For Windows 2000 or later, the proper order of ACEs is more complicated
195da6c28aaSamw * because of the introduction of object-specific ACEs and automatic
196da6c28aaSamw * inheritance.
197da6c28aaSamw *
198da6c28aaSamw * The following describes the preferred order:
199da6c28aaSamw *
200da6c28aaSamw * To ensure that noninherited ACEs have precedence over inherited ACEs,
201da6c28aaSamw * place all noninherited ACEs in a group before any inherited ACEs. This
202da6c28aaSamw * ordering ensures, for example, that a noninherited access-denied ACE
203da6c28aaSamw * is enforced regardless of any inherited ACE that allows access.
204da6c28aaSamw * Within the groups of noninherited ACEs and inherited ACEs, order ACEs
205da6c28aaSamw * according to ACE type, as the following shows:
206da6c28aaSamw * . Access-denied ACEs that apply to the object itself
207da6c28aaSamw * . Access-denied ACEs that apply to a subobject of the
208da6c28aaSamw * object, such as a property set or property
209da6c28aaSamw * . Access-allowed ACEs that apply to the object itself
210da6c28aaSamw * . Access-allowed ACEs that apply to a subobject of the object
211da6c28aaSamw *
21255bf511dSas200622 * So, here is the desired ACE order
213da6c28aaSamw *
214da6c28aaSamw * deny-direct, allow-direct, deny-inherited, allow-inherited
215da6c28aaSamw *
21655bf511dSas200622 * Of course, not all ACE types are required in an ACL.
217da6c28aaSamw */
21855bf511dSas200622 void
smb_acl_sort(smb_acl_t * acl)219da6c28aaSamw smb_acl_sort(smb_acl_t *acl)
220da6c28aaSamw {
221da6c28aaSamw list_t ace_grps[SMB_AG_NUM];
22255bf511dSas200622 list_t *alist;
22355bf511dSas200622 smb_ace_t *ace;
224da6c28aaSamw uint8_t ace_flags;
22555bf511dSas200622 int ag, i;
226da6c28aaSamw
227da6c28aaSamw ASSERT(acl);
228da6c28aaSamw
229da6c28aaSamw if (acl->sl_acecnt == 0) {
230da6c28aaSamw /*
231da6c28aaSamw * ACL with no entry is a valid ACL and it means
232da6c28aaSamw * no access for anybody.
233da6c28aaSamw */
23455bf511dSas200622 return;
235da6c28aaSamw }
236da6c28aaSamw
237da6c28aaSamw for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
23855bf511dSas200622 list_create(&ace_grps[i], sizeof (smb_ace_t),
23955bf511dSas200622 offsetof(smb_ace_t, se_sln));
240da6c28aaSamw }
241da6c28aaSamw
24255bf511dSas200622 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) {
24355bf511dSas200622 ace_flags = ace->se_hdr.se_flags;
244da6c28aaSamw
24555bf511dSas200622 switch (ace->se_hdr.se_type) {
246da6c28aaSamw case ACCESS_DENIED_ACE_TYPE:
24755bf511dSas200622 ag = (ace_flags & INHERITED_ACE) ?
24855bf511dSas200622 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT;
249da6c28aaSamw break;
250da6c28aaSamw
251da6c28aaSamw case ACCESS_ALLOWED_ACE_TYPE:
25255bf511dSas200622 ag = (ace_flags & INHERITED_ACE) ?
25355bf511dSas200622 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT;
254da6c28aaSamw break;
255da6c28aaSamw
256da6c28aaSamw default:
257da6c28aaSamw /*
258da6c28aaSamw * This is the lowest priority group so we put
259da6c28aaSamw * evertything unknown here.
260da6c28aaSamw */
261da6c28aaSamw ag = SMB_AG_ALW_INHRT;
262da6c28aaSamw break;
263da6c28aaSamw }
264da6c28aaSamw
26555bf511dSas200622 /* Add the ACE to the selected group */
26655bf511dSas200622 list_insert_tail(&ace_grps[ag], ace);
267da6c28aaSamw }
268da6c28aaSamw
26955bf511dSas200622 /*
27055bf511dSas200622 * start with highest priority ACE group and append
27155bf511dSas200622 * the ACEs to the ACL.
27255bf511dSas200622 */
27355bf511dSas200622 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) {
27455bf511dSas200622 alist = &ace_grps[i];
27555bf511dSas200622 while ((ace = list_head(alist)) != NULL) {
27655bf511dSas200622 list_remove(alist, ace);
27755bf511dSas200622 list_insert_tail(&acl->sl_sorted, ace);
27855bf511dSas200622 }
279da6c28aaSamw list_destroy(alist);
280da6c28aaSamw }
281da6c28aaSamw }
282da6c28aaSamw
283da6c28aaSamw /*
28455bf511dSas200622 * smb_acl_from_zfs
285da6c28aaSamw *
28655bf511dSas200622 * Converts given ZFS ACL to a Windows ACL.
287da6c28aaSamw *
28855bf511dSas200622 * A pointer to allocated memory for the Win ACL will be
28955bf511dSas200622 * returned upon successful conversion.
290da6c28aaSamw */
29155bf511dSas200622 smb_acl_t *
smb_acl_from_zfs(acl_t * zacl)292f96bd5c8SAlan Wright smb_acl_from_zfs(acl_t *zacl)
293da6c28aaSamw {
29455bf511dSas200622 ace_t *zace;
29555bf511dSas200622 int numaces;
29655bf511dSas200622 smb_acl_t *acl;
29755bf511dSas200622 smb_ace_t *ace;
29855bf511dSas200622 smb_idmap_batch_t sib;
29955bf511dSas200622 smb_idmap_t *sim;
30055bf511dSas200622 idmap_stat idm_stat;
301da6c28aaSamw
30255bf511dSas200622 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt,
30355bf511dSas200622 SMB_IDMAP_ID2SID);
30455bf511dSas200622 if (idm_stat != IDMAP_SUCCESS)
30555bf511dSas200622 return (NULL);
30655bf511dSas200622
307f96bd5c8SAlan Wright if (smb_fsacl_getsids(&sib, zacl) != IDMAP_SUCCESS) {
30855bf511dSas200622 smb_idmap_batch_destroy(&sib);
30955bf511dSas200622 return (NULL);
31055bf511dSas200622 }
31155bf511dSas200622
31255bf511dSas200622 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt);
31355bf511dSas200622
31455bf511dSas200622 sim = sib.sib_maps;
31555bf511dSas200622 for (numaces = 0, zace = zacl->acl_aclp;
31655bf511dSas200622 numaces < zacl->acl_cnt;
31755bf511dSas200622 zace++, numaces++, sim++) {
31855bf511dSas200622 ASSERT(sim->sim_sid);
31955bf511dSas200622 if (sim->sim_sid == NULL) {
32055bf511dSas200622 smb_acl_free(acl);
32155bf511dSas200622 acl = NULL;
32255bf511dSas200622 break;
32355bf511dSas200622 }
32455bf511dSas200622
32555bf511dSas200622 ace = &acl->sl_aces[numaces];
32655bf511dSas200622 ace->se_hdr.se_type = zace->a_type;
32755bf511dSas200622 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags);
32855bf511dSas200622 ace->se_mask = zace->a_access_mask;
3296537f381Sas200622 ace->se_sid = smb_sid_dup(sim->sim_sid);
33055bf511dSas200622 ace->se_hdr.se_bsize = smb_ace_len(ace);
33155bf511dSas200622
33255bf511dSas200622 acl->sl_bsize += ace->se_hdr.se_bsize;
33355bf511dSas200622 }
33455bf511dSas200622
33555bf511dSas200622 smb_idmap_batch_destroy(&sib);
33655bf511dSas200622 return (acl);
337da6c28aaSamw }
338da6c28aaSamw
339da6c28aaSamw /*
34055bf511dSas200622 * smb_acl_to_zfs
341da6c28aaSamw *
34255bf511dSas200622 * Converts given Windows ACL to a ZFS ACL.
34355bf511dSas200622 *
34455bf511dSas200622 * fs_acl will contain a pointer to the created ZFS ACL.
34555bf511dSas200622 * The allocated memory should be freed by calling
34655bf511dSas200622 * smb_fsacl_free().
34755bf511dSas200622 *
34855bf511dSas200622 * Since the output parameter, fs_acl, is allocated in this
34955bf511dSas200622 * function, the caller has to make sure *fs_acl is NULL which
35055bf511dSas200622 * means it's not pointing to any memory.
351da6c28aaSamw */
352da6c28aaSamw uint32_t
smb_acl_to_zfs(smb_acl_t * acl,uint32_t flags,int which_acl,acl_t ** fs_acl)35355bf511dSas200622 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl)
354da6c28aaSamw {
35555bf511dSas200622 smb_ace_t *ace;
35655bf511dSas200622 acl_t *zacl;
35755bf511dSas200622 ace_t *zace;
35855bf511dSas200622 smb_idmap_batch_t sib;
35955bf511dSas200622 smb_idmap_t *sim;
36055bf511dSas200622 idmap_stat idm_stat;
361f96bd5c8SAlan Wright char *sidstr;
362c8ec8eeaSjose borrego int i;
363da6c28aaSamw
36455bf511dSas200622 ASSERT(fs_acl);
36555bf511dSas200622 ASSERT(*fs_acl == NULL);
36655bf511dSas200622
36755bf511dSas200622 if (acl && !smb_acl_isvalid(acl, which_acl))
36855bf511dSas200622 return (NT_STATUS_INVALID_ACL);
36955bf511dSas200622
37055bf511dSas200622 if ((acl == NULL) || (acl->sl_acecnt == 0)) {
37155bf511dSas200622 if (which_acl == SMB_DACL_SECINFO) {
372c8ec8eeaSjose borrego *fs_acl = smb_fsacl_null_empty(acl == NULL);
373da6c28aaSamw }
374da6c28aaSamw
37555bf511dSas200622 return (NT_STATUS_SUCCESS);
376da6c28aaSamw }
377da6c28aaSamw
37855bf511dSas200622 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt,
37955bf511dSas200622 SMB_IDMAP_SID2ID);
38055bf511dSas200622 if (idm_stat != IDMAP_SUCCESS)
38155bf511dSas200622 return (NT_STATUS_INTERNAL_ERROR);
38255bf511dSas200622
383f96bd5c8SAlan Wright sidstr = kmem_alloc(SMB_SID_STRSZ, KM_SLEEP);
38455bf511dSas200622 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags);
38555bf511dSas200622
38655bf511dSas200622 zace = zacl->acl_aclp;
38755bf511dSas200622 ace = acl->sl_aces;
38855bf511dSas200622 sim = sib.sib_maps;
38955bf511dSas200622
39055bf511dSas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
39155bf511dSas200622 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES;
39255bf511dSas200622 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask);
393c8ec8eeaSjose borrego zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags);
394f96bd5c8SAlan Wright zace->a_who = (uid_t)-1;
39555bf511dSas200622
396f96bd5c8SAlan Wright smb_sid_tostr(ace->se_sid, sidstr);
397f96bd5c8SAlan Wright
398f96bd5c8SAlan Wright if (!smb_ace_wellknown_update(sidstr, zace)) {
39955bf511dSas200622 sim->sim_id = &zace->a_who;
40055bf511dSas200622 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim,
401f96bd5c8SAlan Wright ace->se_sid, SMB_IDMAP_UNKNOWN);
40255bf511dSas200622
40355bf511dSas200622 if (idm_stat != IDMAP_SUCCESS) {
404f96bd5c8SAlan Wright kmem_free(sidstr, SMB_SID_STRSZ);
40555bf511dSas200622 smb_fsacl_free(zacl);
40655bf511dSas200622 smb_idmap_batch_destroy(&sib);
40755bf511dSas200622 return (NT_STATUS_INTERNAL_ERROR);
40855bf511dSas200622 }
40955bf511dSas200622 }
410da6c28aaSamw }
411da6c28aaSamw
412f96bd5c8SAlan Wright kmem_free(sidstr, SMB_SID_STRSZ);
413f96bd5c8SAlan Wright
41455bf511dSas200622 idm_stat = smb_idmap_batch_getmappings(&sib);
41555bf511dSas200622 if (idm_stat != IDMAP_SUCCESS) {
41655bf511dSas200622 smb_fsacl_free(zacl);
41755bf511dSas200622 smb_idmap_batch_destroy(&sib);
41855bf511dSas200622 return (NT_STATUS_NONE_MAPPED);
419da6c28aaSamw }
420da6c28aaSamw
42155bf511dSas200622 /*
42255bf511dSas200622 * Set the ACEs group flag based on the type of ID returned.
42355bf511dSas200622 */
42455bf511dSas200622 zace = zacl->acl_aclp;
42555bf511dSas200622 ace = acl->sl_aces;
42655bf511dSas200622 sim = sib.sib_maps;
42755bf511dSas200622 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
428f96bd5c8SAlan Wright if (zace->a_who == (uid_t)-1)
42955bf511dSas200622 continue;
43055bf511dSas200622
43155bf511dSas200622 if (sim->sim_idtype == SMB_IDMAP_GROUP)
43255bf511dSas200622 zace->a_flags |= ACE_IDENTIFIER_GROUP;
43355bf511dSas200622 }
43455bf511dSas200622
43555bf511dSas200622 smb_idmap_batch_destroy(&sib);
43655bf511dSas200622
43755bf511dSas200622 *fs_acl = zacl;
43855bf511dSas200622 return (NT_STATUS_SUCCESS);
439da6c28aaSamw }
440da6c28aaSamw
441f96bd5c8SAlan Wright static boolean_t
smb_ace_wellknown_update(const char * sid,ace_t * zace)442f96bd5c8SAlan Wright smb_ace_wellknown_update(const char *sid, ace_t *zace)
443f96bd5c8SAlan Wright {
444f96bd5c8SAlan Wright struct {
445f96bd5c8SAlan Wright char *sid;
446f96bd5c8SAlan Wright uint16_t flags;
447f96bd5c8SAlan Wright } map[] = {
448f96bd5c8SAlan Wright { NT_WORLD_SIDSTR, ACE_EVERYONE },
449f96bd5c8SAlan Wright { NT_BUILTIN_CURRENT_OWNER_SIDSTR, ACE_OWNER },
450f96bd5c8SAlan Wright { NT_BUILTIN_CURRENT_GROUP_SIDSTR,
451f96bd5c8SAlan Wright (ACE_GROUP | ACE_IDENTIFIER_GROUP) },
452f96bd5c8SAlan Wright };
453f96bd5c8SAlan Wright
454f96bd5c8SAlan Wright int i;
455f96bd5c8SAlan Wright
456f96bd5c8SAlan Wright for (i = 0; i < (sizeof (map) / sizeof (map[0])); ++i) {
457f96bd5c8SAlan Wright if (strcmp(sid, map[i].sid) == 0) {
458f96bd5c8SAlan Wright zace->a_flags |= map[i].flags;
459f96bd5c8SAlan Wright return (B_TRUE);
460f96bd5c8SAlan Wright }
461f96bd5c8SAlan Wright }
462f96bd5c8SAlan Wright
463f96bd5c8SAlan Wright return (B_FALSE);
464f96bd5c8SAlan Wright }
465f96bd5c8SAlan Wright
466da6c28aaSamw /*
467c8ec8eeaSjose borrego * smb_fsacl_getsids
468da6c28aaSamw *
469da6c28aaSamw * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs.
470da6c28aaSamw */
471da6c28aaSamw static idmap_stat
smb_fsacl_getsids(smb_idmap_batch_t * sib,acl_t * zacl)472f96bd5c8SAlan Wright smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl)
473da6c28aaSamw {
474da6c28aaSamw ace_t *zace;
475da6c28aaSamw idmap_stat idm_stat;
476da6c28aaSamw smb_idmap_t *sim;
477*7206bf49SGordon Ross uid_t id = (uid_t)-1;
478da6c28aaSamw int i, idtype;
479da6c28aaSamw
480da6c28aaSamw sim = sib->sib_maps;
481da6c28aaSamw
482da6c28aaSamw for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt;
483da6c28aaSamw zace++, i++, sim++) {
484da6c28aaSamw switch (zace->a_flags & ACE_TYPE_FLAGS) {
485da6c28aaSamw case ACE_OWNER:
486f96bd5c8SAlan Wright idtype = SMB_IDMAP_OWNERAT;
487da6c28aaSamw break;
488da6c28aaSamw
489da6c28aaSamw case (ACE_GROUP | ACE_IDENTIFIER_GROUP):
490da6c28aaSamw /* owning group */
491f96bd5c8SAlan Wright idtype = SMB_IDMAP_GROUPAT;
492da6c28aaSamw break;
493da6c28aaSamw
494da6c28aaSamw case ACE_IDENTIFIER_GROUP:
495da6c28aaSamw /* regular group */
496da6c28aaSamw id = zace->a_who;
497da6c28aaSamw idtype = SMB_IDMAP_GROUP;
498da6c28aaSamw break;
499da6c28aaSamw
500da6c28aaSamw case ACE_EVERYONE:
501da6c28aaSamw idtype = SMB_IDMAP_EVERYONE;
502da6c28aaSamw break;
503da6c28aaSamw
504da6c28aaSamw default:
505da6c28aaSamw /* user entry */
506da6c28aaSamw id = zace->a_who;
507da6c28aaSamw idtype = SMB_IDMAP_USER;
508da6c28aaSamw }
509da6c28aaSamw
510da6c28aaSamw idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim,
511da6c28aaSamw id, idtype);
512da6c28aaSamw
513da6c28aaSamw if (idm_stat != IDMAP_SUCCESS) {
514da6c28aaSamw return (idm_stat);
515da6c28aaSamw }
516da6c28aaSamw }
517da6c28aaSamw
518da6c28aaSamw idm_stat = smb_idmap_batch_getmappings(sib);
519da6c28aaSamw return (idm_stat);
520da6c28aaSamw }
521da6c28aaSamw
522da6c28aaSamw /*
523c8ec8eeaSjose borrego * smb_fsacl_null_empty
524da6c28aaSamw *
525da6c28aaSamw * NULL DACL means everyone full-access
526da6c28aaSamw * Empty DACL means everyone full-deny
527da6c28aaSamw *
528da6c28aaSamw * ZFS ACL must have at least one entry so smb server has
529da6c28aaSamw * to simulate the aforementioned expected behavior by adding
530da6c28aaSamw * an entry in case the requested DACL is null or empty. Adding
531da6c28aaSamw * a everyone full-deny entry has proved to be problematic in
532da6c28aaSamw * tests since a deny entry takes precedence over allow entries.
533da6c28aaSamw * So, instead of adding a everyone full-deny, an owner ACE with
534da6c28aaSamw * owner implicit permissions will be set.
535da6c28aaSamw */
53655bf511dSas200622 static acl_t *
smb_fsacl_null_empty(boolean_t null)537c8ec8eeaSjose borrego smb_fsacl_null_empty(boolean_t null)
538da6c28aaSamw {
539da6c28aaSamw acl_t *zacl;
540da6c28aaSamw ace_t *zace;
541da6c28aaSamw
54255bf511dSas200622 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT);
543da6c28aaSamw zace = zacl->acl_aclp;
544da6c28aaSamw
545da6c28aaSamw zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
546da6c28aaSamw if (null) {
547da6c28aaSamw zace->a_access_mask = ACE_ALL_PERMS;
548da6c28aaSamw zace->a_flags = ACE_EVERYONE;
549da6c28aaSamw } else {
550da6c28aaSamw zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL |
551da6c28aaSamw ACE_READ_ATTRIBUTES;
552da6c28aaSamw zace->a_flags = ACE_OWNER;
553da6c28aaSamw }
554da6c28aaSamw
555da6c28aaSamw return (zacl);
556da6c28aaSamw }
557da6c28aaSamw
558da6c28aaSamw /*
55955bf511dSas200622 * FS ACL (acl_t) Functions
560da6c28aaSamw */
56155bf511dSas200622 acl_t *
smb_fsacl_alloc(int acenum,int flags)56255bf511dSas200622 smb_fsacl_alloc(int acenum, int flags)
563da6c28aaSamw {
56455bf511dSas200622 acl_t *acl;
565da6c28aaSamw
56655bf511dSas200622 acl = acl_alloc(ACE_T);
56755bf511dSas200622 acl->acl_cnt = acenum;
56855bf511dSas200622 acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP);
56955bf511dSas200622 acl->acl_flags = flags;
57055bf511dSas200622 return (acl);
571da6c28aaSamw }
572da6c28aaSamw
57355bf511dSas200622 void
smb_fsacl_free(acl_t * acl)57455bf511dSas200622 smb_fsacl_free(acl_t *acl)
575da6c28aaSamw {
57655bf511dSas200622 if (acl)
57755bf511dSas200622 acl_free(acl);
578da6c28aaSamw }
579da6c28aaSamw
580da6c28aaSamw /*
58155bf511dSas200622 * smb_fsop_aclmerge
582da6c28aaSamw *
58355bf511dSas200622 * smb_fsop_aclread/write routines which interact with filesystem
58455bf511dSas200622 * work with single ACL. This routine merges given DACL and SACL
58555bf511dSas200622 * which might have been created during CIFS to FS conversion into
58655bf511dSas200622 * one single ACL.
58755bf511dSas200622 */
58855bf511dSas200622 acl_t *
smb_fsacl_merge(acl_t * dacl,acl_t * sacl)58955bf511dSas200622 smb_fsacl_merge(acl_t *dacl, acl_t *sacl)
59055bf511dSas200622 {
59155bf511dSas200622 acl_t *acl;
59255bf511dSas200622 int dacl_size;
59355bf511dSas200622
59455bf511dSas200622 ASSERT(dacl);
59555bf511dSas200622 ASSERT(sacl);
59655bf511dSas200622
59755bf511dSas200622 acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags);
59855bf511dSas200622 dacl_size = dacl->acl_cnt * dacl->acl_entry_size;
59955bf511dSas200622 bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size);
60055bf511dSas200622 bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size,
60155bf511dSas200622 sacl->acl_cnt * sacl->acl_entry_size);
60255bf511dSas200622
60355bf511dSas200622 return (acl);
60455bf511dSas200622 }
60555bf511dSas200622
60655bf511dSas200622 /*
60755bf511dSas200622 * smb_fsacl_split
60855bf511dSas200622 *
60955bf511dSas200622 * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on
61055bf511dSas200622 * the 'which_acl' parameter. Note that output dacl/sacl parameters could be
61155bf511dSas200622 * NULL even if they're specified in 'which_acl', which means the target
61255bf511dSas200622 * doesn't have any access and/or audit ACEs.
61355bf511dSas200622 */
61455bf511dSas200622 void
smb_fsacl_split(acl_t * zacl,acl_t ** dacl,acl_t ** sacl,int which_acl)61555bf511dSas200622 smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl)
61655bf511dSas200622 {
61755bf511dSas200622 ace_t *zace;
618*7206bf49SGordon Ross ace_t *access_ace = NULL;
619*7206bf49SGordon Ross ace_t *audit_ace = NULL;
62055bf511dSas200622 int naccess, naudit;
62155bf511dSas200622 int get_dacl, get_sacl;
62255bf511dSas200622 int i;
62355bf511dSas200622
62455bf511dSas200622 *dacl = *sacl = NULL;
62555bf511dSas200622 naccess = naudit = 0;
62655bf511dSas200622 get_dacl = (which_acl & SMB_DACL_SECINFO);
62755bf511dSas200622 get_sacl = (which_acl & SMB_SACL_SECINFO);
62855bf511dSas200622
62955bf511dSas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
63055bf511dSas200622 if (get_dacl && smb_ace_is_access(zace->a_type))
63155bf511dSas200622 naccess++;
63255bf511dSas200622 else if (get_sacl && smb_ace_is_audit(zace->a_type))
63355bf511dSas200622 naudit++;
63455bf511dSas200622 }
63555bf511dSas200622
63655bf511dSas200622 if (naccess) {
63755bf511dSas200622 *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags);
63855bf511dSas200622 access_ace = (*dacl)->acl_aclp;
63955bf511dSas200622 }
64055bf511dSas200622
64155bf511dSas200622 if (naudit) {
64255bf511dSas200622 *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags);
64355bf511dSas200622 audit_ace = (*sacl)->acl_aclp;
64455bf511dSas200622 }
64555bf511dSas200622
64655bf511dSas200622 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
64755bf511dSas200622 if (get_dacl && smb_ace_is_access(zace->a_type)) {
64855bf511dSas200622 *access_ace = *zace;
64955bf511dSas200622 access_ace++;
65055bf511dSas200622 } else if (get_sacl && smb_ace_is_audit(zace->a_type)) {
65155bf511dSas200622 *audit_ace = *zace;
65255bf511dSas200622 audit_ace++;
65355bf511dSas200622 }
65455bf511dSas200622 }
65555bf511dSas200622 }
65655bf511dSas200622
65755bf511dSas200622 /*
65855bf511dSas200622 * ACE Inheritance Rules
65955bf511dSas200622 *
66055bf511dSas200622 * The system propagates inheritable ACEs to child objects according to a
66155bf511dSas200622 * set of inheritance rules. The system places inherited ACEs in the child's
66255bf511dSas200622 * DACL according to the preferred order of ACEs in a DACL. For Windows
66355bf511dSas200622 * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs.
66455bf511dSas200622 *
66555bf511dSas200622 * The following table shows the ACEs inherited by container and noncontainer
66655bf511dSas200622 * child objects for different combinations of inheritance flags. These
66755bf511dSas200622 * inheritance rules work the same for both DACLs and SACLs.
66855bf511dSas200622 *
66955bf511dSas200622 * Parent ACE type Effect on Child ACL
67055bf511dSas200622 * ----------------------- -------------------
67155bf511dSas200622 * OBJECT_INHERIT_ACE only Noncontainer child objects:
67255bf511dSas200622 * Inherited as an effective ACE.
67355bf511dSas200622 * Container child objects:
67455bf511dSas200622 * Containers inherit an inherit-only ACE
67555bf511dSas200622 * unless the NO_PROPAGATE_INHERIT_ACE bit
676da6c28aaSamw * flag is also set.
677da6c28aaSamw *
67855bf511dSas200622 * CONTAINER_INHERIT_ACE only Noncontainer child objects:
67955bf511dSas200622 * No effect on the child object.
68055bf511dSas200622 * Container child objects:
68155bf511dSas200622 * The child object inherits an effective ACE.
682da6c28aaSamw * The inherited ACE is inheritable unless the
68355bf511dSas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set.
68455bf511dSas200622 *
68555bf511dSas200622 * CONTAINER_INHERIT_ACE and
68655bf511dSas200622 * OBJECT_INHERIT_ACE Noncontainer child objects:
68755bf511dSas200622 * Inherited as an effective ACE.
68855bf511dSas200622 * Container child objects:
68955bf511dSas200622 * The child object inherits an effective ACE.
69055bf511dSas200622 * The inherited ACE is inheritable unless the
69155bf511dSas200622 * NO_PROPAGATE_INHERIT_ACE bit flag is also set
69255bf511dSas200622 *
69355bf511dSas200622 * No inheritance flags set No effect on child container or noncontainer
69455bf511dSas200622 * objects.
69555bf511dSas200622 *
69655bf511dSas200622 * If an inherited ACE is an effective ACE for the child object, the system
69755bf511dSas200622 * maps any generic rights to the specific rights for the child object.
69855bf511dSas200622 * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the
69955bf511dSas200622 * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic
70055bf511dSas200622 * rights or generic SIDs are left unchanged so that they can be mapped
70155bf511dSas200622 * appropriately when the ACE is inherited by the next generation of child
70255bf511dSas200622 * objects.
70355bf511dSas200622 *
70455bf511dSas200622 * For a case in which a container object inherits an ACE that is both
70555bf511dSas200622 * effective on the container and inheritable by its descendants, the
70655bf511dSas200622 * container may inherit two ACEs. This occurs if the inheritable ACE
70755bf511dSas200622 * contains generic information. The container inherits an inherit-only
70855bf511dSas200622 * ACE containing the generic information and an effective-only ACE in
70955bf511dSas200622 * which the generic information has been mapped.
710da6c28aaSamw */
711da6c28aaSamw
712*7206bf49SGordon Ross #ifdef _KERNEL
713da6c28aaSamw /*
71455bf511dSas200622 * smb_fsacl_inherit
715da6c28aaSamw *
716da6c28aaSamw * Manufacture the inherited ACL from the given ACL considering
717da6c28aaSamw * the new object type (file/dir) specified by 'is_dir'. The
718da6c28aaSamw * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions.
71955bf511dSas200622 * This function implements Windows inheritance rules explained above.
720da6c28aaSamw *
72155bf511dSas200622 * Note that the in/out ACLs are ZFS ACLs not Windows ACLs
722da6c28aaSamw */
723da6c28aaSamw acl_t *
smb_fsacl_inherit(acl_t * dir_zacl,int is_dir,int which_acl,cred_t * cr)7249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, cred_t *cr)
725da6c28aaSamw {
726da6c28aaSamw boolean_t use_default = B_FALSE;
727da6c28aaSamw int num_inheritable = 0;
728da6c28aaSamw int numaces;
729da6c28aaSamw ace_t *dir_zace;
730da6c28aaSamw acl_t *new_zacl;
731da6c28aaSamw ace_t *new_zace;
7329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ksid_t *owner_sid;
7339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ksid_t *group_sid;
7349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uid_t uid;
7359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States gid_t gid;
7369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
7379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States owner_sid = crgetsid(cr, KSID_OWNER);
7389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States group_sid = crgetsid(cr, KSID_GROUP);
7399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(owner_sid);
7409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(group_sid);
7419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uid = owner_sid->ks_id;
7429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States gid = group_sid->ks_id;
743da6c28aaSamw
74455bf511dSas200622 num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir);
745da6c28aaSamw
746da6c28aaSamw if (num_inheritable == 0) {
747da6c28aaSamw if (which_acl == SMB_DACL_SECINFO) {
748da6c28aaSamw /* No inheritable access ACEs -> default DACL */
749da6c28aaSamw num_inheritable = DEFAULT_DACL_ACENUM;
750da6c28aaSamw use_default = B_TRUE;
751da6c28aaSamw } else {
752da6c28aaSamw return (NULL);
753da6c28aaSamw }
754da6c28aaSamw }
755da6c28aaSamw
75655bf511dSas200622 new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT);
757da6c28aaSamw new_zace = new_zacl->acl_aclp;
758da6c28aaSamw
759da6c28aaSamw if (use_default) {
760da6c28aaSamw bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl));
7619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States new_zace->a_who = uid;
762da6c28aaSamw return (new_zacl);
763da6c28aaSamw }
764da6c28aaSamw
765da6c28aaSamw for (numaces = 0, dir_zace = dir_zacl->acl_aclp;
766da6c28aaSamw numaces < dir_zacl->acl_cnt;
767da6c28aaSamw dir_zace++, numaces++) {
768da6c28aaSamw switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) {
769da6c28aaSamw case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
770da6c28aaSamw /*
771da6c28aaSamw * Files inherit an effective ACE.
772da6c28aaSamw *
773da6c28aaSamw * Dirs inherit an effective ACE.
774da6c28aaSamw * The inherited ACE is inheritable unless the
775da6c28aaSamw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
776da6c28aaSamw */
7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid);
778da6c28aaSamw new_zace++;
779da6c28aaSamw
780da6c28aaSamw if (is_dir && ZACE_IS_CREATOR(dir_zace) &&
781da6c28aaSamw (ZACE_IS_PROPAGATE(dir_zace))) {
782da6c28aaSamw *new_zace = *dir_zace;
783da6c28aaSamw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
784da6c28aaSamw ACE_INHERITED_ACE);
785da6c28aaSamw new_zace++;
786da6c28aaSamw }
787da6c28aaSamw break;
788da6c28aaSamw
789da6c28aaSamw case ACE_FILE_INHERIT_ACE:
790da6c28aaSamw /*
791da6c28aaSamw * Files inherit as an effective ACE.
792da6c28aaSamw *
793da6c28aaSamw * Dirs inherit an inherit-only ACE
794da6c28aaSamw * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
795da6c28aaSamw * flag is also set.
796da6c28aaSamw */
797da6c28aaSamw if (is_dir == 0) {
7989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(dir_zace, new_zace, is_dir,
7999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States uid, gid);
800da6c28aaSamw new_zace++;
801da6c28aaSamw } else if (ZACE_IS_PROPAGATE(dir_zace)) {
802da6c28aaSamw *new_zace = *dir_zace;
803da6c28aaSamw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
804da6c28aaSamw ACE_INHERITED_ACE);
805da6c28aaSamw new_zace++;
806da6c28aaSamw }
807da6c28aaSamw break;
808da6c28aaSamw
809da6c28aaSamw case ACE_DIRECTORY_INHERIT_ACE:
810da6c28aaSamw /*
811da6c28aaSamw * No effect on files
812da6c28aaSamw *
813da6c28aaSamw * Dirs inherit an effective ACE.
814da6c28aaSamw * The inherited ACE is inheritable unless the
815da6c28aaSamw * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
816da6c28aaSamw */
817da6c28aaSamw if (is_dir == 0)
818da6c28aaSamw break;
819da6c28aaSamw
8209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(dir_zace, new_zace, is_dir, uid, gid);
821da6c28aaSamw new_zace++;
822da6c28aaSamw
823da6c28aaSamw if (ZACE_IS_CREATOR(dir_zace) &&
824da6c28aaSamw (ZACE_IS_PROPAGATE(dir_zace))) {
825da6c28aaSamw *new_zace = *dir_zace;
826da6c28aaSamw new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
827da6c28aaSamw ACE_INHERITED_ACE);
828da6c28aaSamw new_zace++;
829da6c28aaSamw }
830da6c28aaSamw
831da6c28aaSamw break;
832da6c28aaSamw
833da6c28aaSamw default:
834da6c28aaSamw break;
835da6c28aaSamw }
836da6c28aaSamw }
837da6c28aaSamw
838da6c28aaSamw return (new_zacl);
839da6c28aaSamw }
840*7206bf49SGordon Ross #endif /* _KERNEL */
841da6c28aaSamw
84255bf511dSas200622 /*
84355bf511dSas200622 * smb_fsacl_from_vsa
84455bf511dSas200622 *
84555bf511dSas200622 * Converts given vsecattr_t structure to a acl_t structure.
84655bf511dSas200622 *
84755bf511dSas200622 * The allocated memory for retuned acl_t should be freed by
84855bf511dSas200622 * calling acl_free().
84955bf511dSas200622 */
85055bf511dSas200622 acl_t *
smb_fsacl_from_vsa(vsecattr_t * vsecattr,acl_type_t acl_type)85155bf511dSas200622 smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type)
85255bf511dSas200622 {
85355bf511dSas200622 int aclbsize = 0; /* size of acl list in bytes */
85455bf511dSas200622 int dfaclbsize = 0; /* size of default acl list in bytes */
85555bf511dSas200622 int numacls;
85655bf511dSas200622 acl_t *acl_info;
85755bf511dSas200622
85855bf511dSas200622 ASSERT(vsecattr);
85955bf511dSas200622
86055bf511dSas200622 acl_info = acl_alloc(acl_type);
86155bf511dSas200622 if (acl_info == NULL)
86255bf511dSas200622 return (NULL);
86355bf511dSas200622
86455bf511dSas200622 acl_info->acl_flags = 0;
86555bf511dSas200622
86655bf511dSas200622 switch (acl_type) {
86755bf511dSas200622
86855bf511dSas200622 case ACLENT_T:
86955bf511dSas200622 numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt;
87055bf511dSas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t);
87155bf511dSas200622 dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t);
87255bf511dSas200622
87355bf511dSas200622 acl_info->acl_cnt = numacls;
87455bf511dSas200622 acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize,
87555bf511dSas200622 KM_SLEEP);
87655bf511dSas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
87755bf511dSas200622 aclbsize);
87855bf511dSas200622 (void) memcpy((char *)acl_info->acl_aclp + aclbsize,
87955bf511dSas200622 vsecattr->vsa_dfaclentp, dfaclbsize);
88055bf511dSas200622
88155bf511dSas200622 if (acl_info->acl_cnt <= MIN_ACL_ENTRIES)
88255bf511dSas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL;
88355bf511dSas200622
88455bf511dSas200622 break;
88555bf511dSas200622
88655bf511dSas200622 case ACE_T:
88755bf511dSas200622 aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
88855bf511dSas200622 acl_info->acl_cnt = vsecattr->vsa_aclcnt;
88955bf511dSas200622 acl_info->acl_flags = vsecattr->vsa_aclflags;
89055bf511dSas200622 acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP);
89155bf511dSas200622 (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
89255bf511dSas200622 aclbsize);
89355bf511dSas200622 if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0)
89455bf511dSas200622 acl_info->acl_flags |= ACL_IS_TRIVIAL;
89555bf511dSas200622
89655bf511dSas200622 break;
89755bf511dSas200622
89855bf511dSas200622 default:
89955bf511dSas200622 acl_free(acl_info);
90055bf511dSas200622 return (NULL);
90155bf511dSas200622 }
90255bf511dSas200622
90355bf511dSas200622 if (aclbsize && vsecattr->vsa_aclentp)
90455bf511dSas200622 kmem_free(vsecattr->vsa_aclentp, aclbsize);
90555bf511dSas200622 if (dfaclbsize && vsecattr->vsa_dfaclentp)
90655bf511dSas200622 kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize);
90755bf511dSas200622
90855bf511dSas200622 return (acl_info);
90955bf511dSas200622 }
91055bf511dSas200622
91155bf511dSas200622 /*
91255bf511dSas200622 * smb_fsacl_to_vsa
91355bf511dSas200622 *
91455bf511dSas200622 * Converts given acl_t structure to a vsecattr_t structure.
91555bf511dSas200622 *
91655bf511dSas200622 * IMPORTANT:
91755bf511dSas200622 * Upon successful return the memory allocated for vsa_aclentp
91855bf511dSas200622 * should be freed by calling kmem_free(). The size is returned
91955bf511dSas200622 * in aclbsize.
92055bf511dSas200622 */
92155bf511dSas200622 int
smb_fsacl_to_vsa(acl_t * acl_info,vsecattr_t * vsecattr,int * aclbsize)92255bf511dSas200622 smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize)
92355bf511dSas200622 {
92455bf511dSas200622 int error = 0;
92555bf511dSas200622 int numacls;
92655bf511dSas200622 aclent_t *aclp;
92755bf511dSas200622
92855bf511dSas200622 ASSERT(acl_info);
92955bf511dSas200622 ASSERT(vsecattr);
93055bf511dSas200622 ASSERT(aclbsize);
93155bf511dSas200622
93255bf511dSas200622 bzero(vsecattr, sizeof (vsecattr_t));
93355bf511dSas200622 *aclbsize = 0;
93455bf511dSas200622
93555bf511dSas200622 switch (acl_info->acl_type) {
93655bf511dSas200622 case ACLENT_T:
93755bf511dSas200622 numacls = acl_info->acl_cnt;
93855bf511dSas200622 /*
93955bf511dSas200622 * Minimum ACL size is three entries so might as well
94055bf511dSas200622 * bail out here. Also limit request size to prevent user
94155bf511dSas200622 * from allocating too much kernel memory. Maximum size
94255bf511dSas200622 * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES
94355bf511dSas200622 * for the default ACL part.
94455bf511dSas200622 */
94555bf511dSas200622 if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) {
94655bf511dSas200622 error = EINVAL;
94755bf511dSas200622 break;
94855bf511dSas200622 }
94955bf511dSas200622
95055bf511dSas200622 vsecattr->vsa_mask = VSA_ACL;
95155bf511dSas200622
95255bf511dSas200622 vsecattr->vsa_aclcnt = numacls;
95355bf511dSas200622 *aclbsize = numacls * sizeof (aclent_t);
95455bf511dSas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
95555bf511dSas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
95655bf511dSas200622 *aclbsize);
95755bf511dSas200622
95855bf511dSas200622 /* Sort the acl list */
95955bf511dSas200622 ksort((caddr_t)vsecattr->vsa_aclentp,
96055bf511dSas200622 vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls);
96155bf511dSas200622
96255bf511dSas200622 /* Break into acl and default acl lists */
96355bf511dSas200622 for (numacls = 0, aclp = vsecattr->vsa_aclentp;
96455bf511dSas200622 numacls < vsecattr->vsa_aclcnt;
96555bf511dSas200622 aclp++, numacls++) {
96655bf511dSas200622 if (aclp->a_type & ACL_DEFAULT)
96755bf511dSas200622 break;
96855bf511dSas200622 }
96955bf511dSas200622
97055bf511dSas200622 /* Find where defaults start (if any) */
97155bf511dSas200622 if (numacls < vsecattr->vsa_aclcnt) {
97255bf511dSas200622 vsecattr->vsa_mask |= VSA_DFACL;
97355bf511dSas200622 vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls;
97455bf511dSas200622 vsecattr->vsa_dfaclentp = aclp;
97555bf511dSas200622 vsecattr->vsa_aclcnt = numacls;
97655bf511dSas200622 }
97755bf511dSas200622
97855bf511dSas200622 /* Adjust if they're all defaults */
97955bf511dSas200622 if (vsecattr->vsa_aclcnt == 0) {
98055bf511dSas200622 vsecattr->vsa_mask &= ~VSA_ACL;
98155bf511dSas200622 vsecattr->vsa_aclentp = NULL;
98255bf511dSas200622 }
98355bf511dSas200622
98455bf511dSas200622 /* Only directories can have defaults */
98555bf511dSas200622 if (vsecattr->vsa_dfaclcnt &&
98655bf511dSas200622 (acl_info->acl_flags & ACL_IS_DIR)) {
98755bf511dSas200622 error = ENOTDIR;
98855bf511dSas200622 }
98955bf511dSas200622
99055bf511dSas200622 break;
99155bf511dSas200622
99255bf511dSas200622 case ACE_T:
99355bf511dSas200622 if (acl_info->acl_cnt < 1 ||
99455bf511dSas200622 acl_info->acl_cnt > MAX_ACL_ENTRIES) {
99555bf511dSas200622 error = EINVAL;
99655bf511dSas200622 break;
99755bf511dSas200622 }
99855bf511dSas200622
99955bf511dSas200622 vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS;
100055bf511dSas200622 vsecattr->vsa_aclcnt = acl_info->acl_cnt;
100155bf511dSas200622 vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL;
100255bf511dSas200622 *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
100355bf511dSas200622 vsecattr->vsa_aclentsz = *aclbsize;
100455bf511dSas200622 vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
100555bf511dSas200622 (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
100655bf511dSas200622 *aclbsize);
100755bf511dSas200622
100855bf511dSas200622 break;
100955bf511dSas200622
101055bf511dSas200622 default:
101155bf511dSas200622 error = EINVAL;
101255bf511dSas200622 }
101355bf511dSas200622
101455bf511dSas200622 return (error);
101555bf511dSas200622 }
101655bf511dSas200622
1017*7206bf49SGordon Ross #ifdef _KERNEL
101855bf511dSas200622 /*
101955bf511dSas200622 * smb_fsacl_inheritable
102055bf511dSas200622 *
102155bf511dSas200622 * Checks to see if there are any inheritable ACEs in the
102255bf511dSas200622 * given ZFS ACL. Returns the number of inheritable ACEs.
102355bf511dSas200622 *
102455bf511dSas200622 * The inherited ACL could be different based on the type of
102555bf511dSas200622 * new object (file/dir) specified by 'is_dir'.
102655bf511dSas200622 *
102755bf511dSas200622 * Note that the input ACL is a ZFS ACL not Windows ACL.
102855bf511dSas200622 */
102955bf511dSas200622 static int
smb_fsacl_inheritable(acl_t * zacl,int is_dir)103055bf511dSas200622 smb_fsacl_inheritable(acl_t *zacl, int is_dir)
103155bf511dSas200622 {
103255bf511dSas200622 int numaces;
103355bf511dSas200622 int num_inheritable = 0;
103455bf511dSas200622 ace_t *zace;
103555bf511dSas200622
103655bf511dSas200622 if (zacl == NULL)
103755bf511dSas200622 return (0);
103855bf511dSas200622
103955bf511dSas200622 for (numaces = 0, zace = zacl->acl_aclp;
104055bf511dSas200622 numaces < zacl->acl_cnt;
104155bf511dSas200622 zace++, numaces++) {
104255bf511dSas200622 switch (zace->a_flags & ACE_FD_INHERIT_ACE) {
104355bf511dSas200622 case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
104455bf511dSas200622 /*
104555bf511dSas200622 * Files inherit an effective ACE.
104655bf511dSas200622 *
104755bf511dSas200622 * Dirs inherit an effective ACE.
104855bf511dSas200622 * The inherited ACE is inheritable unless the
104955bf511dSas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
105055bf511dSas200622 */
105155bf511dSas200622 num_inheritable++;
105255bf511dSas200622
105355bf511dSas200622 if (is_dir && ZACE_IS_CREATOR(zace) &&
105455bf511dSas200622 (ZACE_IS_PROPAGATE(zace))) {
105555bf511dSas200622 num_inheritable++;
105655bf511dSas200622 }
105755bf511dSas200622 break;
105855bf511dSas200622
105955bf511dSas200622 case ACE_FILE_INHERIT_ACE:
106055bf511dSas200622 /*
106155bf511dSas200622 * Files inherit as an effective ACE.
106255bf511dSas200622 *
106355bf511dSas200622 * Dirs inherit an inherit-only ACE
106455bf511dSas200622 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
106555bf511dSas200622 * flag is also set.
106655bf511dSas200622 */
106755bf511dSas200622 if (is_dir == 0)
106855bf511dSas200622 num_inheritable++;
106955bf511dSas200622 else if (ZACE_IS_PROPAGATE(zace))
107055bf511dSas200622 num_inheritable++;
107155bf511dSas200622 break;
107255bf511dSas200622
107355bf511dSas200622 case ACE_DIRECTORY_INHERIT_ACE:
107455bf511dSas200622 /*
107555bf511dSas200622 * No effect on files
107655bf511dSas200622 *
107755bf511dSas200622 * Dirs inherit an effective ACE.
107855bf511dSas200622 * The inherited ACE is inheritable unless the
107955bf511dSas200622 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
108055bf511dSas200622 */
108155bf511dSas200622 if (is_dir == 0)
108255bf511dSas200622 break;
108355bf511dSas200622
108455bf511dSas200622 num_inheritable++;
108555bf511dSas200622
108655bf511dSas200622 if (ZACE_IS_CREATOR(zace) &&
108755bf511dSas200622 (ZACE_IS_PROPAGATE(zace)))
108855bf511dSas200622 num_inheritable++;
108955bf511dSas200622 break;
109055bf511dSas200622
109155bf511dSas200622 default:
109255bf511dSas200622 break;
109355bf511dSas200622 }
109455bf511dSas200622 }
109555bf511dSas200622
109655bf511dSas200622 return (num_inheritable);
109755bf511dSas200622 }
1098*7206bf49SGordon Ross #endif /* _KERNEL */
109955bf511dSas200622
110055bf511dSas200622
110155bf511dSas200622 /*
110255bf511dSas200622 * ACE Functions
110355bf511dSas200622 */
110455bf511dSas200622
110555bf511dSas200622 /*
110655bf511dSas200622 * This is generic (ACL version 2) vs. object-specific
110755bf511dSas200622 * (ACL version 4) ACE types.
110855bf511dSas200622 */
110955bf511dSas200622 boolean_t
smb_ace_is_generic(int type)111055bf511dSas200622 smb_ace_is_generic(int type)
111155bf511dSas200622 {
111255bf511dSas200622 switch (type) {
111355bf511dSas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE:
111455bf511dSas200622 case ACE_ACCESS_DENIED_ACE_TYPE:
111555bf511dSas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE:
111655bf511dSas200622 case ACE_SYSTEM_ALARM_ACE_TYPE:
111755bf511dSas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
111855bf511dSas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
111955bf511dSas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
112055bf511dSas200622 case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE:
112155bf511dSas200622 return (B_TRUE);
112255bf511dSas200622
112355bf511dSas200622 default:
112455bf511dSas200622 break;
112555bf511dSas200622 }
112655bf511dSas200622
112755bf511dSas200622 return (B_FALSE);
112855bf511dSas200622 }
112955bf511dSas200622
113055bf511dSas200622 boolean_t
smb_ace_is_access(int type)113155bf511dSas200622 smb_ace_is_access(int type)
113255bf511dSas200622 {
113355bf511dSas200622 switch (type) {
113455bf511dSas200622 case ACE_ACCESS_ALLOWED_ACE_TYPE:
113555bf511dSas200622 case ACE_ACCESS_DENIED_ACE_TYPE:
113655bf511dSas200622 case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
113755bf511dSas200622 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
113855bf511dSas200622 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
113955bf511dSas200622 case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
114055bf511dSas200622 case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
114155bf511dSas200622 case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
114255bf511dSas200622 case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
114355bf511dSas200622 return (B_TRUE);
114455bf511dSas200622
114555bf511dSas200622 default:
114655bf511dSas200622 break;
114755bf511dSas200622 }
114855bf511dSas200622
114955bf511dSas200622 return (B_FALSE);
115055bf511dSas200622 }
115155bf511dSas200622
115255bf511dSas200622 boolean_t
smb_ace_is_audit(int type)115355bf511dSas200622 smb_ace_is_audit(int type)
115455bf511dSas200622 {
115555bf511dSas200622 switch (type) {
115655bf511dSas200622 case ACE_SYSTEM_AUDIT_ACE_TYPE:
115755bf511dSas200622 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
115855bf511dSas200622 case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
115955bf511dSas200622 case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
116055bf511dSas200622 return (B_TRUE);
116155bf511dSas200622
116255bf511dSas200622 default:
116355bf511dSas200622 break;
116455bf511dSas200622 }
116555bf511dSas200622
116655bf511dSas200622 return (B_FALSE);
116755bf511dSas200622 }
116855bf511dSas200622
116955bf511dSas200622 /*
117055bf511dSas200622 * smb_ace_len
117155bf511dSas200622 *
117255bf511dSas200622 * Returns the length of the given ACE as it appears in an
117355bf511dSas200622 * ACL on the wire (i.e. a flat buffer which contains the SID)
117455bf511dSas200622 */
117555bf511dSas200622 static uint16_t
smb_ace_len(smb_ace_t * ace)117655bf511dSas200622 smb_ace_len(smb_ace_t *ace)
117755bf511dSas200622 {
117855bf511dSas200622 ASSERT(ace);
117955bf511dSas200622 ASSERT(ace->se_sid);
118055bf511dSas200622
118155bf511dSas200622 if (ace == NULL)
118255bf511dSas200622 return (0);
118355bf511dSas200622
118455bf511dSas200622 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) +
11856537f381Sas200622 smb_sid_len(ace->se_sid));
118655bf511dSas200622 }
118755bf511dSas200622
1188*7206bf49SGordon Ross #ifdef _KERNEL
1189da6c28aaSamw static void
smb_ace_inherit(ace_t * dir_zace,ace_t * zace,int is_dir,uid_t uid,gid_t gid)11909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir, uid_t uid, gid_t gid)
1191da6c28aaSamw {
1192da6c28aaSamw *zace = *dir_zace;
1193c8ec8eeaSjose borrego
1194c8ec8eeaSjose borrego /* This is an effective ACE so remove the inherit_only flag */
1195c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_ONLY_ACE;
1196c8ec8eeaSjose borrego /* Mark this ACE as inherited */
1197da6c28aaSamw zace->a_flags |= ACE_INHERITED_ACE;
1198da6c28aaSamw
1199da6c28aaSamw /*
1200c8ec8eeaSjose borrego * If this is a file or NO_PROPAGATE is set then this inherited
1201c8ec8eeaSjose borrego * ACE is not inheritable so clear the inheritance flags
1202c8ec8eeaSjose borrego */
1203c8ec8eeaSjose borrego if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace)))
1204c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_FLAGS;
1205c8ec8eeaSjose borrego
1206c8ec8eeaSjose borrego /*
1207c8ec8eeaSjose borrego * Replace creator owner/group ACEs with actual owner/group ACEs.
12089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * This is a non-inheritable effective ACE.
1209da6c28aaSamw */
1210da6c28aaSamw if (ZACE_IS_CREATOR_OWNER(dir_zace)) {
12119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States zace->a_who = uid;
1212c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_FLAGS;
1213da6c28aaSamw } else if (ZACE_IS_CREATOR_GROUP(dir_zace)) {
12149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States zace->a_who = gid;
12159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States zace->a_flags |= ACE_IDENTIFIER_GROUP;
1216c8ec8eeaSjose borrego zace->a_flags &= ~ACE_INHERIT_FLAGS;
1217da6c28aaSamw }
1218da6c28aaSamw }
1219*7206bf49SGordon Ross #endif /* _KERNEL */
1220da6c28aaSamw
122155bf511dSas200622 /*
122255bf511dSas200622 * smb_ace_mask_g2s
122355bf511dSas200622 *
122455bf511dSas200622 * Converts generic access bits in the given mask (if any)
122555bf511dSas200622 * to file specific bits. Generic access masks shouldn't be
122655bf511dSas200622 * stored in filesystem ACEs.
122755bf511dSas200622 */
122855bf511dSas200622 static uint32_t
smb_ace_mask_g2s(uint32_t mask)122955bf511dSas200622 smb_ace_mask_g2s(uint32_t mask)
123055bf511dSas200622 {
123155bf511dSas200622 if (mask & GENERIC_ALL) {
123255bf511dSas200622 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE
123355bf511dSas200622 | GENERIC_EXECUTE);
123455bf511dSas200622
123555bf511dSas200622 mask |= FILE_ALL_ACCESS;
123655bf511dSas200622 return (mask);
123755bf511dSas200622 }
123855bf511dSas200622
123955bf511dSas200622 if (mask & GENERIC_READ) {
124055bf511dSas200622 mask &= ~GENERIC_READ;
124155bf511dSas200622 mask |= FILE_GENERIC_READ;
124255bf511dSas200622 }
124355bf511dSas200622
124455bf511dSas200622 if (mask & GENERIC_WRITE) {
124555bf511dSas200622 mask &= ~GENERIC_WRITE;
124655bf511dSas200622 mask |= FILE_GENERIC_WRITE;
124755bf511dSas200622 }
124855bf511dSas200622
124955bf511dSas200622 if (mask & GENERIC_EXECUTE) {
125055bf511dSas200622 mask &= ~GENERIC_EXECUTE;
125155bf511dSas200622 mask |= FILE_GENERIC_EXECUTE;
125255bf511dSas200622 }
125355bf511dSas200622
125455bf511dSas200622 return (mask);
125555bf511dSas200622 }
125655bf511dSas200622
1257c8ec8eeaSjose borrego /*
1258c8ec8eeaSjose borrego * smb_ace_flags_tozfs
1259c8ec8eeaSjose borrego *
1260c8ec8eeaSjose borrego * This function maps the flags which have different values
1261c8ec8eeaSjose borrego * in Windows and Solaris. The ones with the same value are
1262c8ec8eeaSjose borrego * transferred untouched.
1263c8ec8eeaSjose borrego */
1264da6c28aaSamw static uint16_t
smb_ace_flags_tozfs(uint8_t c_flags)1265c8ec8eeaSjose borrego smb_ace_flags_tozfs(uint8_t c_flags)
1266da6c28aaSamw {
1267da6c28aaSamw uint16_t z_flags = 0;
1268da6c28aaSamw
1269da6c28aaSamw if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG)
1270da6c28aaSamw z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
1271da6c28aaSamw
1272da6c28aaSamw if (c_flags & FAILED_ACCESS_ACE_FLAG)
1273da6c28aaSamw z_flags |= ACE_FAILED_ACCESS_ACE_FLAG;
1274da6c28aaSamw
1275da6c28aaSamw if (c_flags & INHERITED_ACE)
1276da6c28aaSamw z_flags |= ACE_INHERITED_ACE;
1277da6c28aaSamw
1278da6c28aaSamw z_flags |= (c_flags & ACE_INHERIT_FLAGS);
1279da6c28aaSamw
1280da6c28aaSamw return (z_flags);
1281da6c28aaSamw }
1282da6c28aaSamw
1283da6c28aaSamw static uint8_t
smb_ace_flags_fromzfs(uint16_t z_flags)1284da6c28aaSamw smb_ace_flags_fromzfs(uint16_t z_flags)
1285da6c28aaSamw {
1286da6c28aaSamw uint8_t c_flags;
1287da6c28aaSamw
1288da6c28aaSamw c_flags = z_flags & ACE_INHERIT_FLAGS;
1289da6c28aaSamw
1290da6c28aaSamw if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
1291da6c28aaSamw c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1292da6c28aaSamw
1293da6c28aaSamw if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG)
1294da6c28aaSamw c_flags |= FAILED_ACCESS_ACE_FLAG;
1295da6c28aaSamw
1296da6c28aaSamw if (z_flags & ACE_INHERITED_ACE)
1297da6c28aaSamw c_flags |= INHERITED_ACE;
1298da6c28aaSamw
1299da6c28aaSamw return (c_flags);
1300da6c28aaSamw }
1301da6c28aaSamw
130255bf511dSas200622 static boolean_t
smb_ace_isvalid(smb_ace_t * ace,int which_acl)130355bf511dSas200622 smb_ace_isvalid(smb_ace_t *ace, int which_acl)
130455bf511dSas200622 {
130555bf511dSas200622 uint16_t min_len;
130655bf511dSas200622
130755bf511dSas200622 min_len = sizeof (smb_acehdr_t);
130855bf511dSas200622
130955bf511dSas200622 if (ace->se_hdr.se_bsize < min_len)
131055bf511dSas200622 return (B_FALSE);
131155bf511dSas200622
131255bf511dSas200622 if (smb_ace_is_access(ace->se_hdr.se_type) &&
131355bf511dSas200622 (which_acl != SMB_DACL_SECINFO))
131455bf511dSas200622 return (B_FALSE);
131555bf511dSas200622
131655bf511dSas200622 if (smb_ace_is_audit(ace->se_hdr.se_type) &&
131755bf511dSas200622 (which_acl != SMB_SACL_SECINFO))
131855bf511dSas200622 return (B_FALSE);
131955bf511dSas200622
132055bf511dSas200622 if (smb_ace_is_generic(ace->se_hdr.se_type)) {
13216537f381Sas200622 if (!smb_sid_isvalid(ace->se_sid))
132255bf511dSas200622 return (B_FALSE);
132355bf511dSas200622
132455bf511dSas200622 min_len += sizeof (ace->se_mask);
13256537f381Sas200622 min_len += smb_sid_len(ace->se_sid);
132655bf511dSas200622
132755bf511dSas200622 if (ace->se_hdr.se_bsize < min_len)
132855bf511dSas200622 return (B_FALSE);
132955bf511dSas200622 }
133055bf511dSas200622
1331da6c28aaSamw /*
133255bf511dSas200622 * object-specific ACE validation will be added later.
1333da6c28aaSamw */
133455bf511dSas200622 return (B_TRUE);
1335da6c28aaSamw }
1336