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