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