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