xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_acl.c (revision bbf6f00c25b6a2bed23c35eac6d62998ecdb338c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/acl.h>
27 #include <acl/acl_common.h>
28 #include <smbsrv/smb_sid.h>
29 #include <smbsrv/smb_fsops.h>
30 #include <smbsrv/smb_idmap.h>
31 #include <smbsrv/smb_kproto.h>
32 
33 #define	ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE)
34 
35 #define	ZACE_IS_OWNER(zace) ((zace->a_flags & ACE_TYPE_FLAGS) == ACE_OWNER)
36 #define	ZACE_IS_OWNGRP(zace) \
37 	((zace->a_flags & ACE_TYPE_FLAGS) == (ACE_IDENTIFIER_GROUP|ACE_GROUP))
38 
39 #define	ZACE_IS_USER(zace) \
40 	(((zace->a_flags & ACE_TYPE_FLAGS) == 0) || (ZACE_IS_OWNER(zace)))
41 #define	ZACE_IS_GROUP(zace) (zace->a_flags & ACE_IDENTIFIER_GROUP)
42 #define	ZACE_IS_EVERYONE(zace) (zace->a_flags & ACE_EVERYONE)
43 
44 #define	ZACE_IS_PROPAGATE(zace) \
45 	((zace->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) == 0)
46 
47 #define	ZACE_IS_CREATOR_OWNER(zace) \
48 	(ZACE_IS_USER(zace) && (zace->a_who == IDMAP_WK_CREATOR_OWNER_UID))
49 
50 #define	ZACE_IS_CREATOR_GROUP(zace) \
51 	(ZACE_IS_GROUP(zace) && (zace->a_who == IDMAP_WK_CREATOR_GROUP_GID))
52 
53 #define	ZACE_IS_CREATOR(zace) \
54 	(ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace))
55 
56 /*
57  * ACE groups within a DACL
58  *
59  * This is from lower to higher ACE order priority
60  */
61 #define	SMB_AG_START		0
62 #define	SMB_AG_ALW_INHRT	0
63 #define	SMB_AG_DNY_INHRT	1
64 #define	SMB_AG_ALW_DRCT		2
65 #define	SMB_AG_DNY_DRCT		3
66 #define	SMB_AG_NUM		4
67 
68 /*
69  * SID for Everyone group: S-1-1-0.
70  */
71 smb_sid_t everyone_sid = {
72 	NT_SID_REVISION,
73 	1,
74 	NT_SECURITY_WORLD_AUTH,
75 	{ 0 }
76 };
77 
78 #define	DEFAULT_DACL_ACENUM	2
79 /*
80  * Default ACL:
81  *    owner: full access
82  *    SYSTEM: full access
83  */
84 static ace_t default_dacl[DEFAULT_DACL_ACENUM] = {
85 	{ (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
86 	{ IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
87 	    ACE_ACCESS_ALLOWED_ACE_TYPE }
88 };
89 
90 /*
91  * Note:
92  *
93  * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format
94  * smb_fsacl_xxx functions work with acl_t which represents the Solaris native
95  * format
96  */
97 
98 static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *, uid_t, gid_t);
99 static acl_t *smb_fsacl_null_empty(boolean_t);
100 static int smb_fsacl_inheritable(acl_t *, int);
101 
102 static void smb_ace_inherit(ace_t *, ace_t *, int);
103 static boolean_t smb_ace_isvalid(smb_ace_t *, int);
104 static uint16_t smb_ace_len(smb_ace_t *);
105 static uint32_t smb_ace_mask_g2s(uint32_t);
106 static uint16_t smb_ace_flags_tozfs(uint8_t);
107 static uint8_t smb_ace_flags_fromzfs(uint16_t);
108 
109 smb_acl_t *
110 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt)
111 {
112 	smb_acl_t *acl;
113 	int size;
114 
115 	size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t));
116 	acl = kmem_zalloc(size, KM_SLEEP);
117 	acl->sl_revision = revision;
118 	acl->sl_bsize = bsize;
119 	acl->sl_acecnt = acecnt;
120 	acl->sl_aces = (smb_ace_t *)(acl + 1);
121 
122 	list_create(&acl->sl_sorted, sizeof (smb_ace_t),
123 	    offsetof(smb_ace_t, se_sln));
124 	return (acl);
125 }
126 
127 void
128 smb_acl_free(smb_acl_t *acl)
129 {
130 	int i, size;
131 	void *ace;
132 
133 	if (acl == NULL)
134 		return;
135 
136 	for (i = 0; i < acl->sl_acecnt; i++)
137 		smb_sid_free(acl->sl_aces[i].se_sid);
138 
139 	while ((ace = list_head(&acl->sl_sorted)) != NULL)
140 		list_remove(&acl->sl_sorted, ace);
141 	list_destroy(&acl->sl_sorted);
142 
143 	size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t));
144 	kmem_free(acl, size);
145 }
146 
147 /*
148  * smb_acl_len
149  *
150  * Returns the size of given ACL in bytes. Note that this
151  * is not an in-memory size, it's the ACL's size as it would
152  * appear on the wire
153  */
154 uint16_t
155 smb_acl_len(smb_acl_t *acl)
156 {
157 	return ((acl) ? acl->sl_bsize : 0);
158 }
159 
160 boolean_t
161 smb_acl_isvalid(smb_acl_t *acl, int which_acl)
162 {
163 	int i;
164 
165 	if (acl->sl_bsize < SMB_ACL_HDRSIZE)
166 		return (B_FALSE);
167 
168 	if (acl->sl_revision != ACL_REVISION) {
169 		/*
170 		 * we are rejecting ACLs with object-specific ACEs for now
171 		 */
172 		return (B_FALSE);
173 	}
174 
175 	for (i = 0; i < acl->sl_acecnt; i++) {
176 		if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl))
177 			return (B_FALSE);
178 	}
179 
180 	return (B_TRUE);
181 }
182 
183 /*
184  * smb_acl_sort
185  *
186  * Sorts the given ACL in place if it needs to be sorted.
187  *
188  * The following is an excerpt from MSDN website.
189  *
190  * Order of ACEs in a DACL
191  *
192  * For Windows NT versions 4.0 and earlier, the preferred order of ACEs
193  * is simple: In a DACL, all access-denied ACEs should precede any
194  * access-allowed ACEs.
195  *
196  * For Windows 2000 or later, the proper order of ACEs is more complicated
197  * because of the introduction of object-specific ACEs and automatic
198  * inheritance.
199  *
200  * The following describes the preferred order:
201  *
202  * To ensure that noninherited ACEs have precedence over inherited ACEs,
203  * place all noninherited ACEs in a group before any inherited ACEs. This
204  * ordering ensures, for example, that a noninherited access-denied ACE
205  * is enforced regardless of any inherited ACE that allows access.
206  * Within the groups of noninherited ACEs and inherited ACEs, order ACEs
207  * according to ACE type, as the following shows:
208  * 	. Access-denied ACEs that apply to the object itself
209  * 	. Access-denied ACEs that apply to a subobject of the
210  *	  object, such as a property set or property
211  * 	. Access-allowed ACEs that apply to the object itself
212  * 	. Access-allowed ACEs that apply to a subobject of the object
213  *
214  * So, here is the desired ACE order
215  *
216  * deny-direct, allow-direct, deny-inherited, allow-inherited
217  *
218  * Of course, not all ACE types are required in an ACL.
219  */
220 void
221 smb_acl_sort(smb_acl_t *acl)
222 {
223 	list_t ace_grps[SMB_AG_NUM];
224 	list_t *alist;
225 	smb_ace_t *ace;
226 	uint8_t ace_flags;
227 	int ag, i;
228 
229 	ASSERT(acl);
230 
231 	if (acl->sl_acecnt == 0) {
232 		/*
233 		 * ACL with no entry is a valid ACL and it means
234 		 * no access for anybody.
235 		 */
236 		return;
237 	}
238 
239 	for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
240 		list_create(&ace_grps[i], sizeof (smb_ace_t),
241 		    offsetof(smb_ace_t, se_sln));
242 	}
243 
244 	for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) {
245 		ace_flags = ace->se_hdr.se_flags;
246 
247 		switch (ace->se_hdr.se_type) {
248 		case ACCESS_DENIED_ACE_TYPE:
249 			ag = (ace_flags & INHERITED_ACE) ?
250 			    SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT;
251 			break;
252 
253 		case ACCESS_ALLOWED_ACE_TYPE:
254 			ag = (ace_flags & INHERITED_ACE) ?
255 			    SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT;
256 			break;
257 
258 		default:
259 			/*
260 			 * This is the lowest priority group so we put
261 			 * evertything unknown here.
262 			 */
263 			ag = SMB_AG_ALW_INHRT;
264 			break;
265 		}
266 
267 		/* Add the ACE to the selected group */
268 		list_insert_tail(&ace_grps[ag], ace);
269 	}
270 
271 	/*
272 	 * start with highest priority ACE group and append
273 	 * the ACEs to the ACL.
274 	 */
275 	for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) {
276 		alist = &ace_grps[i];
277 		while ((ace = list_head(alist)) != NULL) {
278 			list_remove(alist, ace);
279 			list_insert_tail(&acl->sl_sorted, ace);
280 		}
281 		list_destroy(alist);
282 	}
283 }
284 
285 /*
286  * smb_acl_from_zfs
287  *
288  * Converts given ZFS ACL to a Windows ACL.
289  *
290  * A pointer to allocated memory for the Win ACL will be
291  * returned upon successful conversion.
292  */
293 smb_acl_t *
294 smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid)
295 {
296 	ace_t *zace;
297 	int numaces;
298 	smb_acl_t *acl;
299 	smb_ace_t *ace;
300 	smb_idmap_batch_t sib;
301 	smb_idmap_t *sim;
302 	idmap_stat idm_stat;
303 
304 	idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt,
305 	    SMB_IDMAP_ID2SID);
306 	if (idm_stat != IDMAP_SUCCESS)
307 		return (NULL);
308 
309 	if (smb_fsacl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) {
310 		smb_idmap_batch_destroy(&sib);
311 		return (NULL);
312 	}
313 
314 	acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt);
315 
316 	sim = sib.sib_maps;
317 	for (numaces = 0, zace = zacl->acl_aclp;
318 	    numaces < zacl->acl_cnt;
319 	    zace++, numaces++, sim++) {
320 		ASSERT(sim->sim_sid);
321 		if (sim->sim_sid == NULL) {
322 			smb_acl_free(acl);
323 			acl = NULL;
324 			break;
325 		}
326 
327 		ace = &acl->sl_aces[numaces];
328 		ace->se_hdr.se_type = zace->a_type;
329 		ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags);
330 		ace->se_mask = zace->a_access_mask;
331 		ace->se_sid = smb_sid_dup(sim->sim_sid);
332 		ace->se_hdr.se_bsize = smb_ace_len(ace);
333 
334 		acl->sl_bsize += ace->se_hdr.se_bsize;
335 	}
336 
337 	smb_idmap_batch_destroy(&sib);
338 	return (acl);
339 }
340 
341 /*
342  * smb_acl_to_zfs
343  *
344  * Converts given Windows ACL to a ZFS ACL.
345  *
346  * fs_acl will contain a pointer to the created ZFS ACL.
347  * The allocated memory should be freed by calling
348  * smb_fsacl_free().
349  *
350  * Since the output parameter, fs_acl, is allocated in this
351  * function, the caller has to make sure *fs_acl is NULL which
352  * means it's not pointing to any memory.
353  */
354 uint32_t
355 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl)
356 {
357 	smb_ace_t *ace;
358 	acl_t *zacl;
359 	ace_t *zace;
360 	smb_idmap_batch_t sib;
361 	smb_idmap_t *sim;
362 	idmap_stat idm_stat;
363 	int i;
364 
365 	ASSERT(fs_acl);
366 	ASSERT(*fs_acl == NULL);
367 
368 	if (acl && !smb_acl_isvalid(acl, which_acl))
369 		return (NT_STATUS_INVALID_ACL);
370 
371 	if ((acl == NULL) || (acl->sl_acecnt == 0)) {
372 		if (which_acl == SMB_DACL_SECINFO) {
373 			*fs_acl = smb_fsacl_null_empty(acl == NULL);
374 		}
375 
376 		return (NT_STATUS_SUCCESS);
377 	}
378 
379 	idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt,
380 	    SMB_IDMAP_SID2ID);
381 	if (idm_stat != IDMAP_SUCCESS)
382 		return (NT_STATUS_INTERNAL_ERROR);
383 
384 	zacl = smb_fsacl_alloc(acl->sl_acecnt, flags);
385 
386 	zace = zacl->acl_aclp;
387 	ace = acl->sl_aces;
388 	sim = sib.sib_maps;
389 
390 	for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
391 		zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES;
392 		zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask);
393 		zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags);
394 
395 		if (smb_sid_cmp(ace->se_sid, &everyone_sid))
396 			zace->a_flags |= ACE_EVERYONE;
397 		else {
398 			sim->sim_id = &zace->a_who;
399 			idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim,
400 			    ace->se_sid, -1);
401 
402 			if (idm_stat != IDMAP_SUCCESS) {
403 				smb_fsacl_free(zacl);
404 				smb_idmap_batch_destroy(&sib);
405 				return (NT_STATUS_INTERNAL_ERROR);
406 			}
407 		}
408 	}
409 
410 	idm_stat = smb_idmap_batch_getmappings(&sib);
411 	if (idm_stat != IDMAP_SUCCESS) {
412 		smb_fsacl_free(zacl);
413 		smb_idmap_batch_destroy(&sib);
414 		return (NT_STATUS_NONE_MAPPED);
415 	}
416 
417 	/*
418 	 * Set the ACEs group flag based on the type of ID returned.
419 	 */
420 	zace = zacl->acl_aclp;
421 	ace = acl->sl_aces;
422 	sim = sib.sib_maps;
423 	for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) {
424 		if (zace->a_flags & ACE_EVERYONE)
425 			continue;
426 
427 		if (sim->sim_idtype == SMB_IDMAP_GROUP)
428 			zace->a_flags |= ACE_IDENTIFIER_GROUP;
429 	}
430 
431 	smb_idmap_batch_destroy(&sib);
432 
433 	*fs_acl = zacl;
434 	return (NT_STATUS_SUCCESS);
435 }
436 
437 /*
438  * smb_fsacl_getsids
439  *
440  * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs.
441  */
442 static idmap_stat
443 smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid)
444 {
445 	ace_t *zace;
446 	idmap_stat idm_stat;
447 	smb_idmap_t *sim;
448 	uid_t id;
449 	int i, idtype;
450 
451 	sim = sib->sib_maps;
452 
453 	for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt;
454 	    zace++, i++, sim++) {
455 		switch (zace->a_flags & ACE_TYPE_FLAGS) {
456 		case ACE_OWNER:
457 			id = uid;
458 			idtype = SMB_IDMAP_USER;
459 			break;
460 
461 		case (ACE_GROUP | ACE_IDENTIFIER_GROUP):
462 			/* owning group */
463 			id = gid;
464 			idtype = SMB_IDMAP_GROUP;
465 			break;
466 
467 		case ACE_IDENTIFIER_GROUP:
468 			/* regular group */
469 			id = zace->a_who;
470 			idtype = SMB_IDMAP_GROUP;
471 			break;
472 
473 		case ACE_EVERYONE:
474 			idtype = SMB_IDMAP_EVERYONE;
475 			break;
476 
477 		default:
478 			/* user entry */
479 			id = zace->a_who;
480 			idtype = SMB_IDMAP_USER;
481 		}
482 
483 		idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim,
484 		    id, idtype);
485 
486 		if (idm_stat != IDMAP_SUCCESS) {
487 			return (idm_stat);
488 		}
489 	}
490 
491 	idm_stat = smb_idmap_batch_getmappings(sib);
492 	return (idm_stat);
493 }
494 
495 /*
496  * smb_fsacl_null_empty
497  *
498  * NULL DACL means everyone full-access
499  * Empty DACL means everyone full-deny
500  *
501  * ZFS ACL must have at least one entry so smb server has
502  * to simulate the aforementioned expected behavior by adding
503  * an entry in case the requested DACL is null or empty. Adding
504  * a everyone full-deny entry has proved to be problematic in
505  * tests since a deny entry takes precedence over allow entries.
506  * So, instead of adding a everyone full-deny, an owner ACE with
507  * owner implicit permissions will be set.
508  */
509 static acl_t *
510 smb_fsacl_null_empty(boolean_t null)
511 {
512 	acl_t *zacl;
513 	ace_t *zace;
514 
515 	zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT);
516 	zace = zacl->acl_aclp;
517 
518 	zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
519 	if (null) {
520 		zace->a_access_mask = ACE_ALL_PERMS;
521 		zace->a_flags = ACE_EVERYONE;
522 	} else {
523 		zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL |
524 		    ACE_READ_ATTRIBUTES;
525 		zace->a_flags = ACE_OWNER;
526 	}
527 
528 	return (zacl);
529 }
530 
531 /*
532  * FS ACL (acl_t) Functions
533  */
534 acl_t *
535 smb_fsacl_alloc(int acenum, int flags)
536 {
537 	acl_t *acl;
538 
539 	acl = acl_alloc(ACE_T);
540 	acl->acl_cnt = acenum;
541 	acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP);
542 	acl->acl_flags = flags;
543 	return (acl);
544 }
545 
546 void
547 smb_fsacl_free(acl_t *acl)
548 {
549 	if (acl)
550 		acl_free(acl);
551 }
552 
553 /*
554  * smb_fsop_aclmerge
555  *
556  * smb_fsop_aclread/write routines which interact with filesystem
557  * work with single ACL. This routine merges given DACL and SACL
558  * which might have been created during CIFS to FS conversion into
559  * one single ACL.
560  */
561 acl_t *
562 smb_fsacl_merge(acl_t *dacl, acl_t *sacl)
563 {
564 	acl_t *acl;
565 	int dacl_size;
566 
567 	ASSERT(dacl);
568 	ASSERT(sacl);
569 
570 	acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags);
571 	dacl_size = dacl->acl_cnt * dacl->acl_entry_size;
572 	bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size);
573 	bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size,
574 	    sacl->acl_cnt * sacl->acl_entry_size);
575 
576 	return (acl);
577 }
578 
579 /*
580  * smb_fsacl_split
581  *
582  * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on
583  * the 'which_acl' parameter. Note that output dacl/sacl parameters could be
584  * NULL even if they're specified in 'which_acl', which means the target
585  * doesn't have any access and/or audit ACEs.
586  */
587 void
588 smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl)
589 {
590 	ace_t *zace;
591 	ace_t *access_ace;
592 	ace_t *audit_ace;
593 	int naccess, naudit;
594 	int get_dacl, get_sacl;
595 	int i;
596 
597 	*dacl = *sacl = NULL;
598 	naccess = naudit = 0;
599 	get_dacl = (which_acl & SMB_DACL_SECINFO);
600 	get_sacl = (which_acl & SMB_SACL_SECINFO);
601 
602 	for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
603 		if (get_dacl && smb_ace_is_access(zace->a_type))
604 			naccess++;
605 		else if (get_sacl && smb_ace_is_audit(zace->a_type))
606 			naudit++;
607 	}
608 
609 	if (naccess) {
610 		*dacl = smb_fsacl_alloc(naccess, zacl->acl_flags);
611 		access_ace = (*dacl)->acl_aclp;
612 	}
613 
614 	if (naudit) {
615 		*sacl = smb_fsacl_alloc(naudit, zacl->acl_flags);
616 		audit_ace = (*sacl)->acl_aclp;
617 	}
618 
619 	for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
620 		if (get_dacl && smb_ace_is_access(zace->a_type)) {
621 			*access_ace = *zace;
622 			access_ace++;
623 		} else if (get_sacl && smb_ace_is_audit(zace->a_type)) {
624 			*audit_ace = *zace;
625 			audit_ace++;
626 		}
627 	}
628 }
629 
630 /*
631  * ACE Inheritance Rules
632  *
633  * The system propagates inheritable ACEs to child objects according to a
634  * set of inheritance rules. The system places inherited ACEs in the child's
635  * DACL according to the preferred order of ACEs in a DACL. For Windows
636  * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs.
637  *
638  * The following table shows the ACEs inherited by container and noncontainer
639  * child objects for different combinations of inheritance flags. These
640  * inheritance rules work the same for both DACLs and SACLs.
641  *
642  * Parent ACE type 			Effect on Child ACL
643  * -----------------------		-------------------
644  * OBJECT_INHERIT_ACE only 		Noncontainer child objects:
645  *					Inherited as an effective ACE.
646  *					Container child objects:
647  *					Containers inherit an inherit-only ACE
648  *					unless the NO_PROPAGATE_INHERIT_ACE bit
649  *					flag is also set.
650  *
651  * CONTAINER_INHERIT_ACE only 		Noncontainer child objects:
652  *					No effect on the child object.
653  *					Container child objects:
654  *				The child object inherits an effective ACE.
655  *				The inherited ACE is inheritable unless the
656  *				NO_PROPAGATE_INHERIT_ACE bit flag is also set.
657  *
658  * CONTAINER_INHERIT_ACE and
659  * OBJECT_INHERIT_ACE 			Noncontainer child objects:
660  *					Inherited as an effective ACE.
661  *					Container child objects:
662  *				The child object inherits an effective ACE.
663  *				The inherited ACE is inheritable unless the
664  *				NO_PROPAGATE_INHERIT_ACE bit flag is also set
665  *
666  * No inheritance flags set 	No effect on child container or noncontainer
667  *				objects.
668  *
669  * If an inherited ACE is an effective ACE for the child object, the system
670  * maps any generic rights to the specific rights for the child object.
671  * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the
672  * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic
673  * rights or generic SIDs are left unchanged so that they can be mapped
674  * appropriately when the ACE is inherited by the next generation of child
675  * objects.
676  *
677  * For a case in which a container object inherits an ACE that is both
678  * effective on the container and inheritable by its descendants, the
679  * container may inherit two ACEs. This occurs if the inheritable ACE
680  * contains generic information. The container inherits an inherit-only
681  * ACE containing the generic information and an effective-only ACE in
682  * which the generic information has been mapped.
683  */
684 
685 /*
686  * smb_fsacl_inherit
687  *
688  * Manufacture the inherited ACL from the given ACL considering
689  * the new object type (file/dir) specified by 'is_dir'. The
690  * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions.
691  * This function implements Windows inheritance rules explained above.
692  *
693  * Note that the in/out ACLs are ZFS ACLs not Windows ACLs
694  */
695 acl_t *
696 smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid)
697 {
698 	boolean_t use_default = B_FALSE;
699 	int num_inheritable = 0;
700 	int numaces;
701 	ace_t *dir_zace;
702 	acl_t *new_zacl;
703 	ace_t *new_zace;
704 
705 	num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir);
706 
707 	if (num_inheritable == 0) {
708 		if (which_acl == SMB_DACL_SECINFO) {
709 			/* No inheritable access ACEs -> default DACL */
710 			num_inheritable = DEFAULT_DACL_ACENUM;
711 			use_default = B_TRUE;
712 		} else {
713 			return (NULL);
714 		}
715 	}
716 
717 	new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT);
718 	new_zace = new_zacl->acl_aclp;
719 
720 	if (use_default) {
721 		bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl));
722 		new_zace->a_who = owner_uid;
723 		return (new_zacl);
724 	}
725 
726 	for (numaces = 0, dir_zace = dir_zacl->acl_aclp;
727 	    numaces < dir_zacl->acl_cnt;
728 	    dir_zace++, numaces++) {
729 		switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) {
730 		case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
731 			/*
732 			 * Files inherit an effective ACE.
733 			 *
734 			 * Dirs inherit an effective ACE.
735 			 * The inherited ACE is inheritable unless the
736 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
737 			 */
738 			smb_ace_inherit(dir_zace, new_zace, is_dir);
739 			new_zace++;
740 
741 			if (is_dir && ZACE_IS_CREATOR(dir_zace) &&
742 			    (ZACE_IS_PROPAGATE(dir_zace))) {
743 				*new_zace = *dir_zace;
744 				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
745 				    ACE_INHERITED_ACE);
746 				new_zace++;
747 			}
748 			break;
749 
750 		case ACE_FILE_INHERIT_ACE:
751 			/*
752 			 * Files inherit as an effective ACE.
753 			 *
754 			 * Dirs inherit an inherit-only ACE
755 			 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
756 			 * flag is also set.
757 			 */
758 			if (is_dir == 0) {
759 				smb_ace_inherit(dir_zace, new_zace, is_dir);
760 				new_zace++;
761 			} else if (ZACE_IS_PROPAGATE(dir_zace)) {
762 				*new_zace = *dir_zace;
763 				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
764 				    ACE_INHERITED_ACE);
765 				new_zace++;
766 			}
767 			break;
768 
769 		case ACE_DIRECTORY_INHERIT_ACE:
770 			/*
771 			 * No effect on files
772 			 *
773 			 * Dirs inherit an effective ACE.
774 			 * The inherited ACE is inheritable unless the
775 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
776 			 */
777 			if (is_dir == 0)
778 				break;
779 
780 			smb_ace_inherit(dir_zace, new_zace, is_dir);
781 			new_zace++;
782 
783 			if (ZACE_IS_CREATOR(dir_zace) &&
784 			    (ZACE_IS_PROPAGATE(dir_zace))) {
785 				*new_zace = *dir_zace;
786 				new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
787 				    ACE_INHERITED_ACE);
788 				new_zace++;
789 			}
790 
791 			break;
792 
793 		default:
794 			break;
795 		}
796 	}
797 
798 	return (new_zacl);
799 }
800 
801 /*
802  * smb_fsacl_from_vsa
803  *
804  * Converts given vsecattr_t structure to a acl_t structure.
805  *
806  * The allocated memory for retuned acl_t should be freed by
807  * calling acl_free().
808  */
809 acl_t *
810 smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type)
811 {
812 	int		aclbsize = 0;	/* size of acl list in bytes */
813 	int		dfaclbsize = 0;	/* size of default acl list in bytes */
814 	int		numacls;
815 	acl_t		*acl_info;
816 
817 	ASSERT(vsecattr);
818 
819 	acl_info = acl_alloc(acl_type);
820 	if (acl_info == NULL)
821 		return (NULL);
822 
823 	acl_info->acl_flags = 0;
824 
825 	switch (acl_type) {
826 
827 	case ACLENT_T:
828 		numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt;
829 		aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t);
830 		dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t);
831 
832 		acl_info->acl_cnt = numacls;
833 		acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize,
834 		    KM_SLEEP);
835 		(void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
836 		    aclbsize);
837 		(void) memcpy((char *)acl_info->acl_aclp + aclbsize,
838 		    vsecattr->vsa_dfaclentp, dfaclbsize);
839 
840 		if (acl_info->acl_cnt <= MIN_ACL_ENTRIES)
841 			acl_info->acl_flags |= ACL_IS_TRIVIAL;
842 
843 		break;
844 
845 	case ACE_T:
846 		aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
847 		acl_info->acl_cnt = vsecattr->vsa_aclcnt;
848 		acl_info->acl_flags = vsecattr->vsa_aclflags;
849 		acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP);
850 		(void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
851 		    aclbsize);
852 		if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0)
853 			acl_info->acl_flags |= ACL_IS_TRIVIAL;
854 
855 		break;
856 
857 	default:
858 		acl_free(acl_info);
859 		return (NULL);
860 	}
861 
862 	if (aclbsize && vsecattr->vsa_aclentp)
863 		kmem_free(vsecattr->vsa_aclentp, aclbsize);
864 	if (dfaclbsize && vsecattr->vsa_dfaclentp)
865 		kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize);
866 
867 	return (acl_info);
868 }
869 
870 /*
871  * smb_fsacl_to_vsa
872  *
873  * Converts given acl_t structure to a vsecattr_t structure.
874  *
875  * IMPORTANT:
876  * Upon successful return the memory allocated for vsa_aclentp
877  * should be freed by calling kmem_free(). The size is returned
878  * in aclbsize.
879  */
880 int
881 smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize)
882 {
883 	int		error = 0;
884 	int		numacls;
885 	aclent_t	*aclp;
886 
887 	ASSERT(acl_info);
888 	ASSERT(vsecattr);
889 	ASSERT(aclbsize);
890 
891 	bzero(vsecattr, sizeof (vsecattr_t));
892 	*aclbsize = 0;
893 
894 	switch (acl_info->acl_type) {
895 	case ACLENT_T:
896 		numacls = acl_info->acl_cnt;
897 		/*
898 		 * Minimum ACL size is three entries so might as well
899 		 * bail out here.  Also limit request size to prevent user
900 		 * from allocating too much kernel memory.  Maximum size
901 		 * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES
902 		 * for the default ACL part.
903 		 */
904 		if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) {
905 			error = EINVAL;
906 			break;
907 		}
908 
909 		vsecattr->vsa_mask = VSA_ACL;
910 
911 		vsecattr->vsa_aclcnt = numacls;
912 		*aclbsize = numacls * sizeof (aclent_t);
913 		vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
914 		(void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
915 		    *aclbsize);
916 
917 		/* Sort the acl list */
918 		ksort((caddr_t)vsecattr->vsa_aclentp,
919 		    vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls);
920 
921 		/* Break into acl and default acl lists */
922 		for (numacls = 0, aclp = vsecattr->vsa_aclentp;
923 		    numacls < vsecattr->vsa_aclcnt;
924 		    aclp++, numacls++) {
925 			if (aclp->a_type & ACL_DEFAULT)
926 				break;
927 		}
928 
929 		/* Find where defaults start (if any) */
930 		if (numacls < vsecattr->vsa_aclcnt) {
931 			vsecattr->vsa_mask |= VSA_DFACL;
932 			vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls;
933 			vsecattr->vsa_dfaclentp = aclp;
934 			vsecattr->vsa_aclcnt = numacls;
935 		}
936 
937 		/* Adjust if they're all defaults */
938 		if (vsecattr->vsa_aclcnt == 0) {
939 			vsecattr->vsa_mask &= ~VSA_ACL;
940 			vsecattr->vsa_aclentp = NULL;
941 		}
942 
943 		/* Only directories can have defaults */
944 		if (vsecattr->vsa_dfaclcnt &&
945 		    (acl_info->acl_flags & ACL_IS_DIR)) {
946 			error = ENOTDIR;
947 		}
948 
949 		break;
950 
951 	case ACE_T:
952 		if (acl_info->acl_cnt < 1 ||
953 		    acl_info->acl_cnt > MAX_ACL_ENTRIES) {
954 			error = EINVAL;
955 			break;
956 		}
957 
958 		vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS;
959 		vsecattr->vsa_aclcnt = acl_info->acl_cnt;
960 		vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL;
961 		*aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
962 		vsecattr->vsa_aclentsz = *aclbsize;
963 		vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
964 		(void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
965 		    *aclbsize);
966 
967 		break;
968 
969 	default:
970 		error = EINVAL;
971 	}
972 
973 	return (error);
974 }
975 
976 /*
977  * smb_fsacl_inheritable
978  *
979  * Checks to see if there are any inheritable ACEs in the
980  * given ZFS ACL. Returns the number of inheritable ACEs.
981  *
982  * The inherited ACL could be different based on the type of
983  * new object (file/dir) specified by 'is_dir'.
984  *
985  * Note that the input ACL is a ZFS ACL not Windows ACL.
986  */
987 static int
988 smb_fsacl_inheritable(acl_t *zacl, int is_dir)
989 {
990 	int numaces;
991 	int num_inheritable = 0;
992 	ace_t *zace;
993 
994 	if (zacl == NULL)
995 		return (0);
996 
997 	for (numaces = 0, zace = zacl->acl_aclp;
998 	    numaces < zacl->acl_cnt;
999 	    zace++, numaces++) {
1000 		switch (zace->a_flags & ACE_FD_INHERIT_ACE) {
1001 		case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
1002 			/*
1003 			 * Files inherit an effective ACE.
1004 			 *
1005 			 * Dirs inherit an effective ACE.
1006 			 * The inherited ACE is inheritable unless the
1007 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
1008 			 */
1009 			num_inheritable++;
1010 
1011 			if (is_dir && ZACE_IS_CREATOR(zace) &&
1012 			    (ZACE_IS_PROPAGATE(zace))) {
1013 				num_inheritable++;
1014 			}
1015 			break;
1016 
1017 		case ACE_FILE_INHERIT_ACE:
1018 			/*
1019 			 * Files inherit as an effective ACE.
1020 			 *
1021 			 * Dirs inherit an inherit-only ACE
1022 			 * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
1023 			 * flag is also set.
1024 			 */
1025 			if (is_dir == 0)
1026 				num_inheritable++;
1027 			else if (ZACE_IS_PROPAGATE(zace))
1028 				num_inheritable++;
1029 			break;
1030 
1031 		case ACE_DIRECTORY_INHERIT_ACE:
1032 			/*
1033 			 * No effect on files
1034 			 *
1035 			 * Dirs inherit an effective ACE.
1036 			 * The inherited ACE is inheritable unless the
1037 			 * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
1038 			 */
1039 			if (is_dir == 0)
1040 				break;
1041 
1042 			num_inheritable++;
1043 
1044 			if (ZACE_IS_CREATOR(zace) &&
1045 			    (ZACE_IS_PROPAGATE(zace)))
1046 				num_inheritable++;
1047 			break;
1048 
1049 		default:
1050 			break;
1051 		}
1052 	}
1053 
1054 	return (num_inheritable);
1055 }
1056 
1057 
1058 /*
1059  * ACE Functions
1060  */
1061 
1062 /*
1063  * This is generic (ACL version 2) vs. object-specific
1064  * (ACL version 4) ACE types.
1065  */
1066 boolean_t
1067 smb_ace_is_generic(int type)
1068 {
1069 	switch (type) {
1070 	case ACE_ACCESS_ALLOWED_ACE_TYPE:
1071 	case ACE_ACCESS_DENIED_ACE_TYPE:
1072 	case ACE_SYSTEM_AUDIT_ACE_TYPE:
1073 	case ACE_SYSTEM_ALARM_ACE_TYPE:
1074 	case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
1075 	case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
1076 	case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
1077 	case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE:
1078 		return (B_TRUE);
1079 
1080 	default:
1081 		break;
1082 	}
1083 
1084 	return (B_FALSE);
1085 }
1086 
1087 boolean_t
1088 smb_ace_is_access(int type)
1089 {
1090 	switch (type) {
1091 	case ACE_ACCESS_ALLOWED_ACE_TYPE:
1092 	case ACE_ACCESS_DENIED_ACE_TYPE:
1093 	case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
1094 	case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
1095 	case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
1096 	case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
1097 	case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
1098 	case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
1099 	case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
1100 		return (B_TRUE);
1101 
1102 	default:
1103 		break;
1104 	}
1105 
1106 	return (B_FALSE);
1107 }
1108 
1109 boolean_t
1110 smb_ace_is_audit(int type)
1111 {
1112 	switch (type) {
1113 	case ACE_SYSTEM_AUDIT_ACE_TYPE:
1114 	case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
1115 	case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
1116 	case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
1117 		return (B_TRUE);
1118 
1119 	default:
1120 		break;
1121 	}
1122 
1123 	return (B_FALSE);
1124 }
1125 
1126 /*
1127  * smb_ace_len
1128  *
1129  * Returns the length of the given ACE as it appears in an
1130  * ACL on the wire (i.e. a flat buffer which contains the SID)
1131  */
1132 static uint16_t
1133 smb_ace_len(smb_ace_t *ace)
1134 {
1135 	ASSERT(ace);
1136 	ASSERT(ace->se_sid);
1137 
1138 	if (ace == NULL)
1139 		return (0);
1140 
1141 	return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) +
1142 	    smb_sid_len(ace->se_sid));
1143 }
1144 
1145 static void
1146 smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir)
1147 {
1148 	*zace = *dir_zace;
1149 
1150 	/* This is an effective ACE so remove the inherit_only flag */
1151 	zace->a_flags &= ~ACE_INHERIT_ONLY_ACE;
1152 	/* Mark this ACE as inherited */
1153 	zace->a_flags |= ACE_INHERITED_ACE;
1154 
1155 	/*
1156 	 * If this is a file or NO_PROPAGATE is set then this inherited
1157 	 * ACE is not inheritable so clear the inheritance flags
1158 	 */
1159 	if (!(is_dir && ZACE_IS_PROPAGATE(dir_zace)))
1160 		zace->a_flags &= ~ACE_INHERIT_FLAGS;
1161 
1162 	/*
1163 	 * Replace creator owner/group ACEs with actual owner/group ACEs.
1164 	 * This would be an effictive ACE which is not inheritable.
1165 	 */
1166 	if (ZACE_IS_CREATOR_OWNER(dir_zace)) {
1167 		zace->a_who = (uid_t)-1;
1168 		zace->a_flags |= ACE_OWNER;
1169 		zace->a_flags &= ~ACE_INHERIT_FLAGS;
1170 	} else if (ZACE_IS_CREATOR_GROUP(dir_zace)) {
1171 		zace->a_who = (uid_t)-1;
1172 		zace->a_flags |= ACE_GROUP;
1173 		zace->a_flags &= ~ACE_INHERIT_FLAGS;
1174 	}
1175 }
1176 
1177 /*
1178  * smb_ace_mask_g2s
1179  *
1180  * Converts generic access bits in the given mask (if any)
1181  * to file specific bits. Generic access masks shouldn't be
1182  * stored in filesystem ACEs.
1183  */
1184 static uint32_t
1185 smb_ace_mask_g2s(uint32_t mask)
1186 {
1187 	if (mask & GENERIC_ALL) {
1188 		mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE
1189 		    | GENERIC_EXECUTE);
1190 
1191 		mask |= FILE_ALL_ACCESS;
1192 		return (mask);
1193 	}
1194 
1195 	if (mask & GENERIC_READ) {
1196 		mask &= ~GENERIC_READ;
1197 		mask |= FILE_GENERIC_READ;
1198 	}
1199 
1200 	if (mask & GENERIC_WRITE) {
1201 		mask &= ~GENERIC_WRITE;
1202 		mask |= FILE_GENERIC_WRITE;
1203 	}
1204 
1205 	if (mask & GENERIC_EXECUTE) {
1206 		mask &= ~GENERIC_EXECUTE;
1207 		mask |= FILE_GENERIC_EXECUTE;
1208 	}
1209 
1210 	return (mask);
1211 }
1212 
1213 /*
1214  * smb_ace_flags_tozfs
1215  *
1216  * This function maps the flags which have different values
1217  * in Windows and Solaris. The ones with the same value are
1218  * transferred untouched.
1219  */
1220 static uint16_t
1221 smb_ace_flags_tozfs(uint8_t c_flags)
1222 {
1223 	uint16_t z_flags = 0;
1224 
1225 	if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG)
1226 		z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
1227 
1228 	if (c_flags & FAILED_ACCESS_ACE_FLAG)
1229 		z_flags |= ACE_FAILED_ACCESS_ACE_FLAG;
1230 
1231 	if (c_flags & INHERITED_ACE)
1232 		z_flags |= ACE_INHERITED_ACE;
1233 
1234 	z_flags |= (c_flags & ACE_INHERIT_FLAGS);
1235 
1236 	return (z_flags);
1237 }
1238 
1239 static uint8_t
1240 smb_ace_flags_fromzfs(uint16_t z_flags)
1241 {
1242 	uint8_t c_flags;
1243 
1244 	c_flags = z_flags & ACE_INHERIT_FLAGS;
1245 
1246 	if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
1247 		c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1248 
1249 	if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG)
1250 		c_flags |= FAILED_ACCESS_ACE_FLAG;
1251 
1252 	if (z_flags & ACE_INHERITED_ACE)
1253 		c_flags |= INHERITED_ACE;
1254 
1255 	return (c_flags);
1256 }
1257 
1258 static boolean_t
1259 smb_ace_isvalid(smb_ace_t *ace, int which_acl)
1260 {
1261 	uint16_t min_len;
1262 
1263 	min_len = sizeof (smb_acehdr_t);
1264 
1265 	if (ace->se_hdr.se_bsize < min_len)
1266 		return (B_FALSE);
1267 
1268 	if (smb_ace_is_access(ace->se_hdr.se_type) &&
1269 	    (which_acl != SMB_DACL_SECINFO))
1270 		return (B_FALSE);
1271 
1272 	if (smb_ace_is_audit(ace->se_hdr.se_type) &&
1273 	    (which_acl != SMB_SACL_SECINFO))
1274 		return (B_FALSE);
1275 
1276 	if (smb_ace_is_generic(ace->se_hdr.se_type)) {
1277 		if (!smb_sid_isvalid(ace->se_sid))
1278 			return (B_FALSE);
1279 
1280 		min_len += sizeof (ace->se_mask);
1281 		min_len += smb_sid_len(ace->se_sid);
1282 
1283 		if (ace->se_hdr.se_bsize < min_len)
1284 			return (B_FALSE);
1285 	}
1286 
1287 	/*
1288 	 * object-specific ACE validation will be added later.
1289 	 */
1290 	return (B_TRUE);
1291 }
1292