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