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