129bd2886SAlan Wright /*
229bd2886SAlan Wright * CDDL HEADER START
329bd2886SAlan Wright *
429bd2886SAlan Wright * The contents of this file are subject to the terms of the
529bd2886SAlan Wright * Common Development and Distribution License (the "License").
629bd2886SAlan Wright * You may not use this file except in compliance with the License.
729bd2886SAlan Wright *
829bd2886SAlan Wright * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
929bd2886SAlan Wright * or http://www.opensolaris.org/os/licensing.
1029bd2886SAlan Wright * See the License for the specific language governing permissions
1129bd2886SAlan Wright * and limitations under the License.
1229bd2886SAlan Wright *
1329bd2886SAlan Wright * When distributing Covered Code, include this CDDL HEADER in each
1429bd2886SAlan Wright * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1529bd2886SAlan Wright * If applicable, add the following below this CDDL HEADER, with the
1629bd2886SAlan Wright * fields enclosed by brackets "[]" replaced with your own identifying
1729bd2886SAlan Wright * information: Portions Copyright [yyyy] [name of copyright owner]
1829bd2886SAlan Wright *
1929bd2886SAlan Wright * CDDL HEADER END
2029bd2886SAlan Wright */
2129bd2886SAlan Wright /*
22f96bd5c8SAlan Wright * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
2329bd2886SAlan Wright * Use is subject to license terms.
24*f920d1d1SGordon Ross *
25*f920d1d1SGordon Ross * Copyright 2023 RackTop Systems, Inc.
26*f920d1d1SGordon Ross */
27*f920d1d1SGordon Ross
28*f920d1d1SGordon Ross /*
29*f920d1d1SGordon Ross * SMB server interfaces for ACL conversion (smb_acl_...)
30*f920d1d1SGordon Ross *
31*f920d1d1SGordon Ross * There are two variants of this interface:
32*f920d1d1SGordon Ross * This is the library version. See also:
33*f920d1d1SGordon Ross * $SRC/uts/common/fs/smbsrv/smb_acl.c
3429bd2886SAlan Wright */
3529bd2886SAlan Wright
3629bd2886SAlan Wright #include <stddef.h>
3729bd2886SAlan Wright #include <strings.h>
38*f920d1d1SGordon Ross #include <syslog.h>
3929bd2886SAlan Wright #include <assert.h>
4029bd2886SAlan Wright
41bbf6f00cSJordan Brown #include <smbsrv/smb.h>
4229bd2886SAlan Wright #include <smbsrv/smb_sid.h>
4329bd2886SAlan Wright #include <smbsrv/smb_idmap.h>
4429bd2886SAlan Wright
4529bd2886SAlan Wright #define ACE_ALL_TYPES 0x001F
4629bd2886SAlan Wright
4729bd2886SAlan Wright /*
4829bd2886SAlan Wright * ACE groups within a DACL
4929bd2886SAlan Wright *
5029bd2886SAlan Wright * This is from lower to higher ACE order priority
5129bd2886SAlan Wright */
5229bd2886SAlan Wright #define SMB_AG_START 0
5329bd2886SAlan Wright #define SMB_AG_ALW_INHRT 0
5429bd2886SAlan Wright #define SMB_AG_DNY_INHRT 1
5529bd2886SAlan Wright #define SMB_AG_ALW_DRCT 2
5629bd2886SAlan Wright #define SMB_AG_DNY_DRCT 3
5729bd2886SAlan Wright #define SMB_AG_NUM 4
5829bd2886SAlan Wright
5929bd2886SAlan Wright #define DEFAULT_DACL_ACENUM 2
6029bd2886SAlan Wright acl_t *acl_alloc(enum acl_type);
6129bd2886SAlan Wright
62f96bd5c8SAlan Wright static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *);
6329bd2886SAlan Wright static acl_t *smb_fsacl_null_empty(boolean_t);
64*f920d1d1SGordon Ross static boolean_t smb_ace_isvalid(smb_ace_t *, int);
6529bd2886SAlan Wright static uint16_t smb_ace_len(smb_ace_t *);
6629bd2886SAlan Wright static uint32_t smb_ace_mask_g2s(uint32_t);
6729bd2886SAlan Wright static uint16_t smb_ace_flags_tozfs(uint8_t);
6829bd2886SAlan Wright static uint8_t smb_ace_flags_fromzfs(uint16_t);
69f96bd5c8SAlan Wright static boolean_t smb_ace_wellknown_update(const char *, ace_t *);
7029bd2886SAlan Wright
7129bd2886SAlan Wright smb_acl_t *
smb_acl_alloc(uint8_t revision,uint16_t bsize,uint16_t acecnt)7229bd2886SAlan Wright smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt)
7329bd2886SAlan Wright {
7429bd2886SAlan Wright smb_acl_t *acl;
7529bd2886SAlan Wright int size;
7629bd2886SAlan Wright
7729bd2886SAlan Wright size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t));
7829bd2886SAlan Wright if ((acl = malloc(size)) == NULL)
7929bd2886SAlan Wright return (NULL);
8029bd2886SAlan Wright
8129bd2886SAlan Wright acl->sl_revision = revision;
8229bd2886SAlan Wright acl->sl_bsize = bsize;
8329bd2886SAlan Wright acl->sl_acecnt = acecnt;
8429bd2886SAlan Wright acl->sl_aces = (smb_ace_t *)(acl + 1);
8529bd2886SAlan Wright
8629bd2886SAlan Wright list_create(&acl->sl_sorted, sizeof (smb_ace_t),
8729bd2886SAlan Wright offsetof(smb_ace_t, se_sln));
8829bd2886SAlan Wright return (acl);
8929bd2886SAlan Wright }
9029bd2886SAlan Wright
9129bd2886SAlan Wright void
smb_acl_free(smb_acl_t * acl)9229bd2886SAlan Wright smb_acl_free(smb_acl_t *acl)
9329bd2886SAlan Wright {
9429bd2886SAlan Wright int i;
9529bd2886SAlan Wright void *ace;
9629bd2886SAlan Wright
9729bd2886SAlan Wright if (acl == NULL)
9829bd2886SAlan Wright return;
9929bd2886SAlan Wright
10029bd2886SAlan Wright for (i = 0; i < acl->sl_acecnt; i++)
10129bd2886SAlan Wright smb_sid_free(acl->sl_aces[i].se_sid);
10229bd2886SAlan Wright
10329bd2886SAlan Wright while ((ace = list_head(&acl->sl_sorted)) != NULL)
10429bd2886SAlan Wright list_remove(&acl->sl_sorted, ace);
10529bd2886SAlan Wright list_destroy(&acl->sl_sorted);
10629bd2886SAlan Wright free(acl);
10729bd2886SAlan Wright }
10829bd2886SAlan Wright
10929bd2886SAlan Wright /*
11029bd2886SAlan Wright * smb_acl_len
11129bd2886SAlan Wright *
11229bd2886SAlan Wright * Returns the size of given ACL in bytes. Note that this
11329bd2886SAlan Wright * is not an in-memory size, it's the ACL's size as it would
11429bd2886SAlan Wright * appear on the wire
11529bd2886SAlan Wright */
11629bd2886SAlan Wright uint16_t
smb_acl_len(smb_acl_t * acl)11729bd2886SAlan Wright smb_acl_len(smb_acl_t *acl)
11829bd2886SAlan Wright {
11929bd2886SAlan Wright return ((acl) ? acl->sl_bsize : 0);
12029bd2886SAlan Wright }
12129bd2886SAlan Wright
12229bd2886SAlan Wright boolean_t
smb_acl_isvalid(smb_acl_t * acl,int which_acl)123*f920d1d1SGordon Ross smb_acl_isvalid(smb_acl_t *acl, int which_acl)
12429bd2886SAlan Wright {
125*f920d1d1SGordon Ross int i;
126*f920d1d1SGordon Ross
12729bd2886SAlan Wright if (acl->sl_bsize < SMB_ACL_HDRSIZE)
12829bd2886SAlan Wright return (B_FALSE);
12929bd2886SAlan Wright
13029bd2886SAlan Wright if (acl->sl_revision != ACL_REVISION) {
13129bd2886SAlan Wright /*
13229bd2886SAlan Wright * we are rejecting ACLs with object-specific ACEs for now
13329bd2886SAlan Wright */
13429bd2886SAlan Wright return (B_FALSE);
13529bd2886SAlan Wright }
13629bd2886SAlan Wright
137*f920d1d1SGordon Ross for (i = 0; i < acl->sl_acecnt; i++) {
138*f920d1d1SGordon Ross if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl))
139*f920d1d1SGordon Ross return (B_FALSE);
140*f920d1d1SGordon Ross }
141*f920d1d1SGordon Ross
14229bd2886SAlan Wright return (B_TRUE);
14329bd2886SAlan Wright }
14429bd2886SAlan Wright
14529bd2886SAlan Wright /*
14629bd2886SAlan Wright * smb_acl_sort
14729bd2886SAlan Wright *
14829bd2886SAlan Wright * Sorts the given ACL in place if it needs to be sorted.
14929bd2886SAlan Wright *
15029bd2886SAlan Wright * The following is an excerpt from MSDN website.
15129bd2886SAlan Wright *
15229bd2886SAlan Wright * Order of ACEs in a DACL
15329bd2886SAlan Wright *
15429bd2886SAlan Wright * For Windows NT versions 4.0 and earlier, the preferred order of ACEs
15529bd2886SAlan Wright * is simple: In a DACL, all access-denied ACEs should precede any
15629bd2886SAlan Wright * access-allowed ACEs.
15729bd2886SAlan Wright *
15829bd2886SAlan Wright * For Windows 2000 or later, the proper order of ACEs is more complicated
15929bd2886SAlan Wright * because of the introduction of object-specific ACEs and automatic
16029bd2886SAlan Wright * inheritance.
16129bd2886SAlan Wright *
16229bd2886SAlan Wright * The following describes the preferred order:
16329bd2886SAlan Wright *
16429bd2886SAlan Wright * To ensure that noninherited ACEs have precedence over inherited ACEs,
16529bd2886SAlan Wright * place all noninherited ACEs in a group before any inherited ACEs. This
16629bd2886SAlan Wright * ordering ensures, for example, that a noninherited access-denied ACE
16729bd2886SAlan Wright * is enforced regardless of any inherited ACE that allows access.
16829bd2886SAlan Wright * Within the groups of noninherited ACEs and inherited ACEs, order ACEs
16929bd2886SAlan Wright * according to ACE type, as the following shows:
17029bd2886SAlan Wright * . Access-denied ACEs that apply to the object itself
17129bd2886SAlan Wright * . Access-denied ACEs that apply to a subobject of the
17229bd2886SAlan Wright * object, such as a property set or property
17329bd2886SAlan Wright * . Access-allowed ACEs that apply to the object itself
17429bd2886SAlan Wright * . Access-allowed ACEs that apply to a subobject of the object
17529bd2886SAlan Wright *
17629bd2886SAlan Wright * So, here is the desired ACE order
17729bd2886SAlan Wright *
17829bd2886SAlan Wright * deny-direct, allow-direct, deny-inherited, allow-inherited
17929bd2886SAlan Wright *
18029bd2886SAlan Wright * Of course, not all ACE types are required in an ACL.
18129bd2886SAlan Wright */
18229bd2886SAlan Wright void
smb_acl_sort(smb_acl_t * acl)18329bd2886SAlan Wright smb_acl_sort(smb_acl_t *acl)
18429bd2886SAlan Wright {
18529bd2886SAlan Wright list_t ace_grps[SMB_AG_NUM];
18629bd2886SAlan Wright list_t *alist;
18729bd2886SAlan Wright smb_ace_t *ace;
18829bd2886SAlan Wright uint8_t ace_flags;
18929bd2886SAlan Wright int ag, i;
19029bd2886SAlan Wright
19129bd2886SAlan Wright assert(acl);
19229bd2886SAlan Wright
19329bd2886SAlan Wright if (acl->sl_acecnt == 0) {
19429bd2886SAlan Wright /*
19529bd2886SAlan Wright * ACL with no entry is a valid ACL and it means
19629bd2886SAlan Wright * no access for anybody.
19729bd2886SAlan Wright */
19829bd2886SAlan Wright return;
19929bd2886SAlan Wright }
20029bd2886SAlan Wright
20129bd2886SAlan Wright for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
20229bd2886SAlan Wright list_create(&ace_grps[i], sizeof (smb_ace_t),
20329bd2886SAlan Wright offsetof(smb_ace_t, se_sln));
20429bd2886SAlan Wright }
20529bd2886SAlan Wright
20629bd2886SAlan Wright for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) {
20729bd2886SAlan Wright ace_flags = ace->se_hdr.se_flags;
20829bd2886SAlan Wright
20929bd2886SAlan Wright switch (ace->se_hdr.se_type) {
21029bd2886SAlan Wright case ACCESS_DENIED_ACE_TYPE:
21129bd2886SAlan Wright ag = (ace_flags & INHERITED_ACE) ?
21229bd2886SAlan Wright SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT;
21329bd2886SAlan Wright break;
21429bd2886SAlan Wright
21529bd2886SAlan Wright case ACCESS_ALLOWED_ACE_TYPE:
21629bd2886SAlan Wright ag = (ace_flags & INHERITED_ACE) ?
21729bd2886SAlan Wright SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT;
21829bd2886SAlan Wright break;
21929bd2886SAlan Wright
22029bd2886SAlan Wright default:
22129bd2886SAlan Wright /*
22229bd2886SAlan Wright * This is the lowest priority group so we put
22329bd2886SAlan Wright * evertything unknown here.
22429bd2886SAlan Wright */
22529bd2886SAlan Wright ag = SMB_AG_ALW_INHRT;
22629bd2886SAlan Wright break;
22729bd2886SAlan Wright }
22829bd2886SAlan Wright
22929bd2886SAlan Wright /* Add the ACE to the selected group */
23029bd2886SAlan Wright list_insert_tail(&ace_grps[ag], ace);
23129bd2886SAlan Wright }
23229bd2886SAlan Wright
23329bd2886SAlan Wright /*
23429bd2886SAlan Wright * start with highest priority ACE group and append
23529bd2886SAlan Wright * the ACEs to the ACL.
23629bd2886SAlan Wright */
23729bd2886SAlan Wright for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) {
23829bd2886SAlan Wright alist = &ace_grps[i];
23929bd2886SAlan Wright while ((ace = list_head(alist)) != NULL) {
24029bd2886SAlan Wright list_remove(alist, ace);
24129bd2886SAlan Wright list_insert_tail(&acl->sl_sorted, ace);
24229bd2886SAlan Wright }
24329bd2886SAlan Wright list_destroy(alist);
24429bd2886SAlan Wright }
24529bd2886SAlan Wright }
24629bd2886SAlan Wright
24729bd2886SAlan Wright /*
248*f920d1d1SGordon Ross * Error handling call-back for smb_idmap_batch_getmappings.
249*f920d1d1SGordon Ross * Would be nice if this could report the path, but that's not
250*f920d1d1SGordon Ross * passed down here. For now, use a dtrace fbt probe here.
251*f920d1d1SGordon Ross */
252*f920d1d1SGordon Ross static void
smb_acl_bgm_error(smb_idmap_batch_t * sib,smb_idmap_t * sim)253*f920d1d1SGordon Ross smb_acl_bgm_error(smb_idmap_batch_t *sib, smb_idmap_t *sim)
254*f920d1d1SGordon Ross {
255*f920d1d1SGordon Ross
256*f920d1d1SGordon Ross if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) != 0)
257*f920d1d1SGordon Ross return;
258*f920d1d1SGordon Ross
259*f920d1d1SGordon Ross if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) {
260*f920d1d1SGordon Ross /*
261*f920d1d1SGordon Ross * Note: The ID and type we asked idmap to map
262*f920d1d1SGordon Ross * were saved in *sim_id and sim_idtype.
263*f920d1d1SGordon Ross */
264*f920d1d1SGordon Ross uid_t id = (sim->sim_id == NULL) ? (uid_t)-1 : *sim->sim_id;
265*f920d1d1SGordon Ross syslog(LOG_ERR, "!smb_acl: Can't get SID for "
266*f920d1d1SGordon Ross "ID=%u type=%d, status=%d",
267*f920d1d1SGordon Ross id, sim->sim_idtype, sim->sim_stat);
268*f920d1d1SGordon Ross }
269*f920d1d1SGordon Ross
270*f920d1d1SGordon Ross if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) {
271*f920d1d1SGordon Ross syslog(LOG_ERR, "!smb_acl: Can't get ID for "
272*f920d1d1SGordon Ross "SID %s-%u, status=%d",
273*f920d1d1SGordon Ross sim->sim_domsid, sim->sim_rid, sim->sim_stat);
274*f920d1d1SGordon Ross }
275*f920d1d1SGordon Ross }
276*f920d1d1SGordon Ross
277*f920d1d1SGordon Ross /*
27829bd2886SAlan Wright * smb_acl_from_zfs
27929bd2886SAlan Wright *
28029bd2886SAlan Wright * Converts given ZFS ACL to a Windows ACL.
28129bd2886SAlan Wright *
28229bd2886SAlan Wright * A pointer to allocated memory for the Windows ACL will be
28329bd2886SAlan Wright * returned upon successful conversion.
28429bd2886SAlan Wright */
28529bd2886SAlan Wright smb_acl_t *
smb_acl_from_zfs(acl_t * zacl)286f96bd5c8SAlan Wright smb_acl_from_zfs(acl_t *zacl)
28729bd2886SAlan Wright {
28829bd2886SAlan Wright ace_t *zace;
28929bd2886SAlan Wright int numaces;
29029bd2886SAlan Wright smb_acl_t *acl;
29129bd2886SAlan Wright smb_ace_t *ace;
29229bd2886SAlan Wright smb_idmap_batch_t sib;
29329bd2886SAlan Wright smb_idmap_t *sim;
29429bd2886SAlan Wright idmap_stat idm_stat;
29529bd2886SAlan Wright
29629bd2886SAlan Wright idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt,
29729bd2886SAlan Wright SMB_IDMAP_ID2SID);
29829bd2886SAlan Wright if (idm_stat != IDMAP_SUCCESS)
29929bd2886SAlan Wright return (NULL);
30029bd2886SAlan Wright
301*f920d1d1SGordon Ross /*
302*f920d1d1SGordon Ross * Note that smb_fsacl_getsids sets up references in
303*f920d1d1SGordon Ross * sib.sib_maps to the zace->a_who fields that live
304*f920d1d1SGordon Ross * until smb_idmap_batch_destroy is called.
305*f920d1d1SGordon Ross */
306f96bd5c8SAlan Wright if (smb_fsacl_getsids(&sib, zacl) != IDMAP_SUCCESS) {
30729bd2886SAlan Wright smb_idmap_batch_destroy(&sib);
30829bd2886SAlan Wright return (NULL);
30929bd2886SAlan Wright }
31029bd2886SAlan Wright
31129bd2886SAlan Wright acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt);
31229bd2886SAlan Wright
31329bd2886SAlan Wright sim = sib.sib_maps;
31429bd2886SAlan Wright for (numaces = 0, zace = zacl->acl_aclp;
31529bd2886SAlan Wright numaces < zacl->acl_cnt;
31629bd2886SAlan Wright zace++, numaces++, sim++) {
31729bd2886SAlan Wright assert(sim->sim_sid);
31829bd2886SAlan Wright if (sim->sim_sid == NULL) {
31929bd2886SAlan Wright smb_acl_free(acl);
32029bd2886SAlan Wright acl = NULL;
32129bd2886SAlan Wright break;
32229bd2886SAlan Wright }
32329bd2886SAlan Wright
32429bd2886SAlan Wright ace = &acl->sl_aces[numaces];
32529bd2886SAlan Wright ace->se_hdr.se_type = zace->a_type;
32629bd2886SAlan Wright ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags);
32729bd2886SAlan Wright ace->se_mask = zace->a_access_mask;
32829bd2886SAlan Wright ace->se_sid = smb_sid_dup(sim->sim_sid);
32929bd2886SAlan Wright ace->se_hdr.se_bsize = smb_ace_len(ace);
33029bd2886SAlan Wright
33129bd2886SAlan Wright acl->sl_bsize += ace->se_hdr.se_bsize;
33229bd2886SAlan Wright }
33329bd2886SAlan Wright
33429bd2886SAlan Wright smb_idmap_batch_destroy(&sib);
33529bd2886SAlan Wright return (acl);
33629bd2886SAlan Wright }
33729bd2886SAlan Wright
33829bd2886SAlan Wright /*
33929bd2886SAlan Wright * smb_acl_to_zfs
34029bd2886SAlan Wright *
34129bd2886SAlan Wright * Converts given Windows ACL to a ZFS ACL.
34229bd2886SAlan Wright *
34329bd2886SAlan Wright * fs_acl will contain a pointer to the created ZFS ACL.
34429bd2886SAlan Wright * The allocated memory should be freed by calling
34529bd2886SAlan Wright * smb_fsacl_free().
34629bd2886SAlan Wright *
34729bd2886SAlan Wright * Since the output parameter, fs_acl, is allocated in this
34829bd2886SAlan Wright * function, the caller has to make sure *fs_acl is NULL which
34929bd2886SAlan Wright * means it's not pointing to any memory.
35029bd2886SAlan Wright */
35129bd2886SAlan Wright uint32_t
smb_acl_to_zfs(smb_acl_t * acl,uint32_t flags,int which_acl,acl_t ** fs_acl)35229bd2886SAlan Wright smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl)
35329bd2886SAlan Wright {
354f96bd5c8SAlan Wright char sidstr[SMB_SID_STRSZ];
35529bd2886SAlan Wright smb_ace_t *ace;
35629bd2886SAlan Wright acl_t *zacl;
35729bd2886SAlan Wright ace_t *zace;
35829bd2886SAlan Wright smb_idmap_batch_t sib;
35929bd2886SAlan Wright smb_idmap_t *sim;
36029bd2886SAlan Wright idmap_stat idm_stat;
36129bd2886SAlan Wright int i;
36229bd2886SAlan Wright
36329bd2886SAlan Wright assert(fs_acl);
36429bd2886SAlan Wright assert(*fs_acl == NULL);
36529bd2886SAlan Wright
36629bd2886SAlan Wright if (acl && !smb_acl_isvalid(acl, which_acl))
36729bd2886SAlan Wright return (NT_STATUS_INVALID_ACL);
36829bd2886SAlan Wright
36929bd2886SAlan Wright if ((acl == NULL) || (acl->sl_acecnt == 0)) {
37029bd2886SAlan Wright if (which_acl == SMB_DACL_SECINFO) {
37129bd2886SAlan Wright *fs_acl = smb_fsacl_null_empty(acl == NULL);
37229bd2886SAlan Wright }
37329bd2886SAlan Wright
37429bd2886SAlan Wright return (NT_STATUS_SUCCESS);
37529bd2886SAlan Wright }
37629bd2886SAlan Wright
37729bd2886SAlan Wright idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt,
37829bd2886SAlan Wright SMB_IDMAP_SID2ID);
37929bd2886SAlan Wright if (idm_stat != IDMAP_SUCCESS)
38029bd2886SAlan Wright return (NT_STATUS_INTERNAL_ERROR);
38129bd2886SAlan Wright
38229bd2886SAlan Wright zacl = smb_fsacl_alloc(acl->sl_acecnt, flags);
38329bd2886SAlan Wright
38429bd2886SAlan Wright zace = zacl->acl_aclp;
38529bd2886SAlan Wright ace = acl->sl_aces;
38629bd2886SAlan Wright sim = sib.sib_maps;
38729bd2886SAlan Wright
38829bd2886SAlan Wright for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
38929bd2886SAlan Wright zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES;
39029bd2886SAlan Wright zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask);
39129bd2886SAlan Wright zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags);
392f96bd5c8SAlan Wright zace->a_who = (uid_t)-1;
39329bd2886SAlan Wright
394f96bd5c8SAlan Wright smb_sid_tostr(ace->se_sid, sidstr);
395f96bd5c8SAlan Wright
396f96bd5c8SAlan Wright if (!smb_ace_wellknown_update(sidstr, zace)) {
39729bd2886SAlan Wright sim->sim_id = &zace->a_who;
39829bd2886SAlan Wright idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim,
399f96bd5c8SAlan Wright ace->se_sid, SMB_IDMAP_UNKNOWN);
40029bd2886SAlan Wright
40129bd2886SAlan Wright if (idm_stat != IDMAP_SUCCESS) {
40229bd2886SAlan Wright smb_fsacl_free(zacl);
40329bd2886SAlan Wright smb_idmap_batch_destroy(&sib);
40429bd2886SAlan Wright return (NT_STATUS_INTERNAL_ERROR);
40529bd2886SAlan Wright }
40629bd2886SAlan Wright }
40729bd2886SAlan Wright }
40829bd2886SAlan Wright
409*f920d1d1SGordon Ross idm_stat = smb_idmap_batch_getmappings(&sib, smb_acl_bgm_error);
41029bd2886SAlan Wright if (idm_stat != IDMAP_SUCCESS) {
41129bd2886SAlan Wright smb_fsacl_free(zacl);
41229bd2886SAlan Wright smb_idmap_batch_destroy(&sib);
41329bd2886SAlan Wright return (NT_STATUS_NONE_MAPPED);
41429bd2886SAlan Wright }
41529bd2886SAlan Wright
41629bd2886SAlan Wright /*
41729bd2886SAlan Wright * Set the ACEs group flag based on the type of ID returned.
41829bd2886SAlan Wright */
41929bd2886SAlan Wright zace = zacl->acl_aclp;
42029bd2886SAlan Wright ace = acl->sl_aces;
42129bd2886SAlan Wright sim = sib.sib_maps;
42229bd2886SAlan Wright for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
423f96bd5c8SAlan Wright if (zace->a_who == (uid_t)-1)
42429bd2886SAlan Wright continue;
42529bd2886SAlan Wright
42629bd2886SAlan Wright if (sim->sim_idtype == SMB_IDMAP_GROUP)
42729bd2886SAlan Wright zace->a_flags |= ACE_IDENTIFIER_GROUP;
42829bd2886SAlan Wright }
42929bd2886SAlan Wright
43029bd2886SAlan Wright smb_idmap_batch_destroy(&sib);
43129bd2886SAlan Wright
43229bd2886SAlan Wright *fs_acl = zacl;
43329bd2886SAlan Wright return (NT_STATUS_SUCCESS);
43429bd2886SAlan Wright }
43529bd2886SAlan Wright
436f96bd5c8SAlan Wright static boolean_t
smb_ace_wellknown_update(const char * sid,ace_t * zace)437f96bd5c8SAlan Wright smb_ace_wellknown_update(const char *sid, ace_t *zace)
438f96bd5c8SAlan Wright {
439f96bd5c8SAlan Wright struct {
440f96bd5c8SAlan Wright char *sid;
441f96bd5c8SAlan Wright uint16_t flags;
442f96bd5c8SAlan Wright } map[] = {
443f96bd5c8SAlan Wright { NT_WORLD_SIDSTR, ACE_EVERYONE },
444f96bd5c8SAlan Wright { NT_BUILTIN_CURRENT_OWNER_SIDSTR, ACE_OWNER },
445f96bd5c8SAlan Wright { NT_BUILTIN_CURRENT_GROUP_SIDSTR,
446f96bd5c8SAlan Wright (ACE_GROUP | ACE_IDENTIFIER_GROUP) },
447f96bd5c8SAlan Wright };
448f96bd5c8SAlan Wright
449f96bd5c8SAlan Wright int i;
450f96bd5c8SAlan Wright
451f96bd5c8SAlan Wright for (i = 0; i < (sizeof (map) / sizeof (map[0])); ++i) {
452f96bd5c8SAlan Wright if (strcmp(sid, map[i].sid) == 0) {
453f96bd5c8SAlan Wright zace->a_flags |= map[i].flags;
454f96bd5c8SAlan Wright return (B_TRUE);
455f96bd5c8SAlan Wright }
456f96bd5c8SAlan Wright }
457f96bd5c8SAlan Wright
458f96bd5c8SAlan Wright return (B_FALSE);
459f96bd5c8SAlan Wright }
460f96bd5c8SAlan Wright
46129bd2886SAlan Wright /*
46229bd2886SAlan Wright * smb_fsacl_getsids
46329bd2886SAlan Wright *
46429bd2886SAlan Wright * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs.
465*f920d1d1SGordon Ross * Note: sib is type SMB_IDMAP_ID2SID, zacl->acl_cnt entries.
46629bd2886SAlan Wright */
46729bd2886SAlan Wright static idmap_stat
smb_fsacl_getsids(smb_idmap_batch_t * sib,acl_t * zacl)468f96bd5c8SAlan Wright smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl)
46929bd2886SAlan Wright {
47029bd2886SAlan Wright ace_t *zace;
47129bd2886SAlan Wright idmap_stat idm_stat;
47229bd2886SAlan Wright smb_idmap_t *sim;
47329bd2886SAlan Wright uid_t id;
47429bd2886SAlan Wright int i, idtype;
47529bd2886SAlan Wright
47629bd2886SAlan Wright sim = sib->sib_maps;
47729bd2886SAlan Wright
47829bd2886SAlan Wright for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt;
47929bd2886SAlan Wright zace++, i++, sim++) {
48083163ba8SToomas Soome id = (uid_t)-1; /* some types do not need id */
48129bd2886SAlan Wright switch (zace->a_flags & ACE_TYPE_FLAGS) {
48229bd2886SAlan Wright case ACE_OWNER:
483f96bd5c8SAlan Wright idtype = SMB_IDMAP_OWNERAT;
48429bd2886SAlan Wright break;
48529bd2886SAlan Wright
48629bd2886SAlan Wright case (ACE_GROUP | ACE_IDENTIFIER_GROUP):
48729bd2886SAlan Wright /* owning group */
488f96bd5c8SAlan Wright idtype = SMB_IDMAP_GROUPAT;
48929bd2886SAlan Wright break;
49029bd2886SAlan Wright
49129bd2886SAlan Wright case ACE_IDENTIFIER_GROUP:
49229bd2886SAlan Wright /* regular group */
49329bd2886SAlan Wright idtype = SMB_IDMAP_GROUP;
494*f920d1d1SGordon Ross id = zace->a_who;
495*f920d1d1SGordon Ross /* for smb_acl_bgm_error ID2SID */
496*f920d1d1SGordon Ross sim->sim_id = &zace->a_who;
49729bd2886SAlan Wright break;
49829bd2886SAlan Wright
49929bd2886SAlan Wright case ACE_EVERYONE:
50029bd2886SAlan Wright idtype = SMB_IDMAP_EVERYONE;
50129bd2886SAlan Wright break;
50229bd2886SAlan Wright
50329bd2886SAlan Wright default:
50429bd2886SAlan Wright /* user entry */
50529bd2886SAlan Wright idtype = SMB_IDMAP_USER;
506*f920d1d1SGordon Ross id = zace->a_who;
507*f920d1d1SGordon Ross /* for smb_acl_bgm_error ID2SID */
508*f920d1d1SGordon Ross sim->sim_id = &zace->a_who;
509*f920d1d1SGordon Ross break;
51029bd2886SAlan Wright }
51129bd2886SAlan Wright
51229bd2886SAlan Wright idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim,
51329bd2886SAlan Wright id, idtype);
51429bd2886SAlan Wright
51529bd2886SAlan Wright if (idm_stat != IDMAP_SUCCESS) {
51629bd2886SAlan Wright return (idm_stat);
51729bd2886SAlan Wright }
51829bd2886SAlan Wright }
51929bd2886SAlan Wright
520*f920d1d1SGordon Ross idm_stat = smb_idmap_batch_getmappings(sib, smb_acl_bgm_error);
52129bd2886SAlan Wright return (idm_stat);
52229bd2886SAlan Wright }
52329bd2886SAlan Wright
52429bd2886SAlan Wright /*
52529bd2886SAlan Wright * smb_fsacl_null_empty
52629bd2886SAlan Wright *
52729bd2886SAlan Wright * NULL DACL means everyone full-access
52829bd2886SAlan Wright * Empty DACL means everyone full-deny
52929bd2886SAlan Wright *
53029bd2886SAlan Wright * ZFS ACL must have at least one entry so smb server has
53129bd2886SAlan Wright * to simulate the aforementioned expected behavior by adding
53229bd2886SAlan Wright * an entry in case the requested DACL is null or empty. Adding
53329bd2886SAlan Wright * a everyone full-deny entry has proved to be problematic in
53429bd2886SAlan Wright * tests since a deny entry takes precedence over allow entries.
53529bd2886SAlan Wright * So, instead of adding a everyone full-deny, an owner ACE with
53629bd2886SAlan Wright * owner implicit permissions will be set.
53729bd2886SAlan Wright */
53829bd2886SAlan Wright static acl_t *
smb_fsacl_null_empty(boolean_t null)53929bd2886SAlan Wright smb_fsacl_null_empty(boolean_t null)
54029bd2886SAlan Wright {
54129bd2886SAlan Wright acl_t *zacl;
54229bd2886SAlan Wright ace_t *zace;
54329bd2886SAlan Wright
54429bd2886SAlan Wright zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT);
54529bd2886SAlan Wright zace = zacl->acl_aclp;
54629bd2886SAlan Wright
54729bd2886SAlan Wright zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
54829bd2886SAlan Wright if (null) {
54929bd2886SAlan Wright zace->a_access_mask = ACE_ALL_PERMS;
55029bd2886SAlan Wright zace->a_flags = ACE_EVERYONE;
55129bd2886SAlan Wright } else {
55229bd2886SAlan Wright zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL |
55329bd2886SAlan Wright ACE_READ_ATTRIBUTES;
55429bd2886SAlan Wright zace->a_flags = ACE_OWNER;
55529bd2886SAlan Wright }
55629bd2886SAlan Wright
55729bd2886SAlan Wright return (zacl);
55829bd2886SAlan Wright }
55929bd2886SAlan Wright
56029bd2886SAlan Wright /*
56129bd2886SAlan Wright * FS ACL (acl_t) Functions
56229bd2886SAlan Wright */
56329bd2886SAlan Wright acl_t *
smb_fsacl_alloc(int acenum,int flags)56429bd2886SAlan Wright smb_fsacl_alloc(int acenum, int flags)
56529bd2886SAlan Wright {
56629bd2886SAlan Wright acl_t *acl;
56729bd2886SAlan Wright
56829bd2886SAlan Wright acl = acl_alloc(ACE_T);
56929bd2886SAlan Wright acl->acl_cnt = acenum;
57029bd2886SAlan Wright if ((acl->acl_aclp = malloc(acl->acl_entry_size * acenum)) == NULL)
57129bd2886SAlan Wright return (NULL);
57229bd2886SAlan Wright
57329bd2886SAlan Wright acl->acl_flags = flags;
57429bd2886SAlan Wright return (acl);
57529bd2886SAlan Wright }
57629bd2886SAlan Wright
57729bd2886SAlan Wright void
smb_fsacl_free(acl_t * acl)57829bd2886SAlan Wright smb_fsacl_free(acl_t *acl)
57929bd2886SAlan Wright {
58029bd2886SAlan Wright if (acl)
58129bd2886SAlan Wright acl_free(acl);
58229bd2886SAlan Wright }
58329bd2886SAlan Wright
58429bd2886SAlan Wright /*
58529bd2886SAlan Wright * ACE Functions
58629bd2886SAlan Wright */
58729bd2886SAlan Wright
58829bd2886SAlan Wright /*
589*f920d1d1SGordon Ross * This is generic (ACL version 2) vs. object-specific
590*f920d1d1SGordon Ross * (ACL version 4) ACE types.
591*f920d1d1SGordon Ross */
592*f920d1d1SGordon Ross boolean_t
smb_ace_is_generic(int type)593*f920d1d1SGordon Ross smb_ace_is_generic(int type)
594*f920d1d1SGordon Ross {
595*f920d1d1SGordon Ross switch (type) {
596*f920d1d1SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE:
597*f920d1d1SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE:
598*f920d1d1SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE:
599*f920d1d1SGordon Ross case ACE_SYSTEM_ALARM_ACE_TYPE:
600*f920d1d1SGordon Ross case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
601*f920d1d1SGordon Ross case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
602*f920d1d1SGordon Ross case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
603*f920d1d1SGordon Ross case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE:
604*f920d1d1SGordon Ross return (B_TRUE);
605*f920d1d1SGordon Ross
606*f920d1d1SGordon Ross default:
607*f920d1d1SGordon Ross break;
608*f920d1d1SGordon Ross }
609*f920d1d1SGordon Ross
610*f920d1d1SGordon Ross return (B_FALSE);
611*f920d1d1SGordon Ross }
612*f920d1d1SGordon Ross
613*f920d1d1SGordon Ross boolean_t
smb_ace_is_access(int type)614*f920d1d1SGordon Ross smb_ace_is_access(int type)
615*f920d1d1SGordon Ross {
616*f920d1d1SGordon Ross switch (type) {
617*f920d1d1SGordon Ross case ACE_ACCESS_ALLOWED_ACE_TYPE:
618*f920d1d1SGordon Ross case ACE_ACCESS_DENIED_ACE_TYPE:
619*f920d1d1SGordon Ross case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
620*f920d1d1SGordon Ross case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
621*f920d1d1SGordon Ross case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
622*f920d1d1SGordon Ross case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
623*f920d1d1SGordon Ross case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
624*f920d1d1SGordon Ross case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
625*f920d1d1SGordon Ross case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
626*f920d1d1SGordon Ross return (B_TRUE);
627*f920d1d1SGordon Ross
628*f920d1d1SGordon Ross default:
629*f920d1d1SGordon Ross break;
630*f920d1d1SGordon Ross }
631*f920d1d1SGordon Ross
632*f920d1d1SGordon Ross return (B_FALSE);
633*f920d1d1SGordon Ross }
634*f920d1d1SGordon Ross
635*f920d1d1SGordon Ross boolean_t
smb_ace_is_audit(int type)636*f920d1d1SGordon Ross smb_ace_is_audit(int type)
637*f920d1d1SGordon Ross {
638*f920d1d1SGordon Ross switch (type) {
639*f920d1d1SGordon Ross case ACE_SYSTEM_AUDIT_ACE_TYPE:
640*f920d1d1SGordon Ross case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
641*f920d1d1SGordon Ross case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
642*f920d1d1SGordon Ross case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
643*f920d1d1SGordon Ross return (B_TRUE);
644*f920d1d1SGordon Ross
645*f920d1d1SGordon Ross default:
646*f920d1d1SGordon Ross break;
647*f920d1d1SGordon Ross }
648*f920d1d1SGordon Ross
649*f920d1d1SGordon Ross return (B_FALSE);
650*f920d1d1SGordon Ross }
651*f920d1d1SGordon Ross
652*f920d1d1SGordon Ross /*
65329bd2886SAlan Wright * smb_ace_len
65429bd2886SAlan Wright *
65529bd2886SAlan Wright * Returns the length of the given ACE as it appears in an
65629bd2886SAlan Wright * ACL on the wire (i.e. a flat buffer which contains the SID)
65729bd2886SAlan Wright */
65829bd2886SAlan Wright static uint16_t
smb_ace_len(smb_ace_t * ace)65929bd2886SAlan Wright smb_ace_len(smb_ace_t *ace)
66029bd2886SAlan Wright {
66129bd2886SAlan Wright assert(ace);
66229bd2886SAlan Wright assert(ace->se_sid);
66329bd2886SAlan Wright
66429bd2886SAlan Wright if (ace == NULL)
66529bd2886SAlan Wright return (0);
66629bd2886SAlan Wright
66729bd2886SAlan Wright return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) +
66829bd2886SAlan Wright smb_sid_len(ace->se_sid));
66929bd2886SAlan Wright }
67029bd2886SAlan Wright
67129bd2886SAlan Wright /*
67229bd2886SAlan Wright * smb_ace_mask_g2s
67329bd2886SAlan Wright *
67429bd2886SAlan Wright * Converts generic access bits in the given mask (if any)
67529bd2886SAlan Wright * to file specific bits. Generic access masks shouldn't be
67629bd2886SAlan Wright * stored in filesystem ACEs.
67729bd2886SAlan Wright */
67829bd2886SAlan Wright static uint32_t
smb_ace_mask_g2s(uint32_t mask)67929bd2886SAlan Wright smb_ace_mask_g2s(uint32_t mask)
68029bd2886SAlan Wright {
68129bd2886SAlan Wright if (mask & GENERIC_ALL) {
68229bd2886SAlan Wright mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE
68329bd2886SAlan Wright | GENERIC_EXECUTE);
68429bd2886SAlan Wright
68529bd2886SAlan Wright mask |= FILE_ALL_ACCESS;
68629bd2886SAlan Wright return (mask);
68729bd2886SAlan Wright }
68829bd2886SAlan Wright
68929bd2886SAlan Wright if (mask & GENERIC_READ) {
69029bd2886SAlan Wright mask &= ~GENERIC_READ;
69129bd2886SAlan Wright mask |= FILE_GENERIC_READ;
69229bd2886SAlan Wright }
69329bd2886SAlan Wright
69429bd2886SAlan Wright if (mask & GENERIC_WRITE) {
69529bd2886SAlan Wright mask &= ~GENERIC_WRITE;
69629bd2886SAlan Wright mask |= FILE_GENERIC_WRITE;
69729bd2886SAlan Wright }
69829bd2886SAlan Wright
69929bd2886SAlan Wright if (mask & GENERIC_EXECUTE) {
70029bd2886SAlan Wright mask &= ~GENERIC_EXECUTE;
70129bd2886SAlan Wright mask |= FILE_GENERIC_EXECUTE;
70229bd2886SAlan Wright }
70329bd2886SAlan Wright
70429bd2886SAlan Wright return (mask);
70529bd2886SAlan Wright }
70629bd2886SAlan Wright
70729bd2886SAlan Wright /*
70829bd2886SAlan Wright * smb_ace_flags_tozfs
70929bd2886SAlan Wright *
71029bd2886SAlan Wright * This function maps the flags which have different values
71129bd2886SAlan Wright * in Windows and Solaris. The ones with the same value are
71229bd2886SAlan Wright * transferred untouched.
71329bd2886SAlan Wright */
71429bd2886SAlan Wright static uint16_t
smb_ace_flags_tozfs(uint8_t c_flags)71529bd2886SAlan Wright smb_ace_flags_tozfs(uint8_t c_flags)
71629bd2886SAlan Wright {
71729bd2886SAlan Wright uint16_t z_flags = 0;
71829bd2886SAlan Wright
71929bd2886SAlan Wright if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG)
72029bd2886SAlan Wright z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
72129bd2886SAlan Wright
72229bd2886SAlan Wright if (c_flags & FAILED_ACCESS_ACE_FLAG)
72329bd2886SAlan Wright z_flags |= ACE_FAILED_ACCESS_ACE_FLAG;
72429bd2886SAlan Wright
72529bd2886SAlan Wright if (c_flags & INHERITED_ACE)
72629bd2886SAlan Wright z_flags |= ACE_INHERITED_ACE;
72729bd2886SAlan Wright
72829bd2886SAlan Wright z_flags |= (c_flags & ACE_INHERIT_FLAGS);
72929bd2886SAlan Wright
73029bd2886SAlan Wright return (z_flags);
73129bd2886SAlan Wright }
73229bd2886SAlan Wright
73329bd2886SAlan Wright static uint8_t
smb_ace_flags_fromzfs(uint16_t z_flags)73429bd2886SAlan Wright smb_ace_flags_fromzfs(uint16_t z_flags)
73529bd2886SAlan Wright {
73629bd2886SAlan Wright uint8_t c_flags;
73729bd2886SAlan Wright
73829bd2886SAlan Wright c_flags = z_flags & ACE_INHERIT_FLAGS;
73929bd2886SAlan Wright
74029bd2886SAlan Wright if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
74129bd2886SAlan Wright c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
74229bd2886SAlan Wright
74329bd2886SAlan Wright if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG)
74429bd2886SAlan Wright c_flags |= FAILED_ACCESS_ACE_FLAG;
74529bd2886SAlan Wright
74629bd2886SAlan Wright if (z_flags & ACE_INHERITED_ACE)
74729bd2886SAlan Wright c_flags |= INHERITED_ACE;
74829bd2886SAlan Wright
74929bd2886SAlan Wright return (c_flags);
75029bd2886SAlan Wright }
751*f920d1d1SGordon Ross
752*f920d1d1SGordon Ross static boolean_t
smb_ace_isvalid(smb_ace_t * ace,int which_acl)753*f920d1d1SGordon Ross smb_ace_isvalid(smb_ace_t *ace, int which_acl)
754*f920d1d1SGordon Ross {
755*f920d1d1SGordon Ross uint16_t min_len;
756*f920d1d1SGordon Ross
757*f920d1d1SGordon Ross min_len = sizeof (smb_acehdr_t);
758*f920d1d1SGordon Ross
759*f920d1d1SGordon Ross if (ace->se_hdr.se_bsize < min_len)
760*f920d1d1SGordon Ross return (B_FALSE);
761*f920d1d1SGordon Ross
762*f920d1d1SGordon Ross if (smb_ace_is_access(ace->se_hdr.se_type) &&
763*f920d1d1SGordon Ross (which_acl != SMB_DACL_SECINFO))
764*f920d1d1SGordon Ross return (B_FALSE);
765*f920d1d1SGordon Ross
766*f920d1d1SGordon Ross if (smb_ace_is_audit(ace->se_hdr.se_type) &&
767*f920d1d1SGordon Ross (which_acl != SMB_SACL_SECINFO))
768*f920d1d1SGordon Ross return (B_FALSE);
769*f920d1d1SGordon Ross
770*f920d1d1SGordon Ross if (smb_ace_is_generic(ace->se_hdr.se_type)) {
771*f920d1d1SGordon Ross if (!smb_sid_isvalid(ace->se_sid))
772*f920d1d1SGordon Ross return (B_FALSE);
773*f920d1d1SGordon Ross
774*f920d1d1SGordon Ross min_len += sizeof (ace->se_mask);
775*f920d1d1SGordon Ross min_len += smb_sid_len(ace->se_sid);
776*f920d1d1SGordon Ross
777*f920d1d1SGordon Ross if (ace->se_hdr.se_bsize < min_len)
778*f920d1d1SGordon Ross return (B_FALSE);
779*f920d1d1SGordon Ross }
780*f920d1d1SGordon Ross
781*f920d1d1SGordon Ross /*
782*f920d1d1SGordon Ross * object-specific ACE validation will be added later.
783*f920d1d1SGordon Ross */
784*f920d1d1SGordon Ross return (B_TRUE);
785*f920d1d1SGordon Ross }
786