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