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