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