Home | History | Annotate | Download | only in nfs
      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 /*
     29  * The following naming convention is used in function names.
     30  *
     31  * If an argument is one or more aclent_t, we use "aent".
     32  * If an argument is one or more nfsace4, we use "ace4".
     33  * If an argument is one or more ace_t, we use "acet".
     34  *
     35  * If there is an aggregate of the one above...
     36  *     If it's contained in a vsecattr_t, we prepend "vs_".
     37  *     If it's contained in an "array" (pointer) and length, we prepend "ln_".
     38  *
     39  * Thus, for example, suppose you have a function that converts an
     40  * array of aclent_t structures into an array of nfsace4 structures,
     41  * it's name would be "ln_aent_to_ace4".
     42  */
     43 
     44 #include <sys/acl.h>
     45 #include <nfs/nfs4_kprot.h>
     46 #include <nfs/nfs4.h>
     47 #include <nfs/rnode4.h>
     48 #include <sys/cmn_err.h>
     49 #include <sys/systm.h>
     50 #include <sys/sdt.h>
     51 
     52 #define	ACE4_POSIX_SUPPORTED_BITS (ACE4_READ_DATA | \
     53     ACE4_WRITE_DATA | \
     54     ACE4_APPEND_DATA | \
     55     ACE4_EXECUTE | \
     56     ACE4_READ_ATTRIBUTES | \
     57     ACE4_READ_ACL | \
     58     ACE4_WRITE_ACL)
     59 
     60 static int ace4vals_compare(const void *, const void *);
     61 static int nfs4_ace4_list_construct(void *, void *, int);
     62 static void nfs4_ace4_list_destroy(void *, void *);
     63 static void ace4_list_free(ace4_list_t *);
     64 static void ace4vals_init(ace4vals_t *, utf8string *);
     65 static void ace4_list_init(ace4_list_t *, int);
     66 static int ln_aent_preprocess(aclent_t *, int,
     67     int *, o_mode_t *, int *, int *, int *);
     68 static void ace4_make_deny(nfsace4 *, nfsace4 *, int, int, int);
     69 static acemask4 mode_to_ace4_access(o_mode_t, int, int, int, int);
     70 static int ln_aent_to_ace4(aclent_t *, int, nfsace4 **, int *, int, int);
     71 static int ace4_mask_to_mode(acemask4, o_mode_t *, int);
     72 static int ace4_allow_to_mode(acemask4, o_mode_t *, int);
     73 static ace4vals_t *ace4vals_find(nfsace4 *, avl_tree_t *, int *);
     74 static int ace4_to_aent_legal(nfsace4 *, int);
     75 static int ace4vals_to_aent(ace4vals_t *, aclent_t *, ace4_list_t *,
     76     uid_t, gid_t, int, int, int);
     77 static int ace4_list_to_aent(ace4_list_t *, aclent_t **, int *, uid_t, gid_t,
     78     int, int, int);
     79 static int ln_ace4_to_aent(nfsace4 *ace4, int n, uid_t, gid_t,
     80     aclent_t **, int *, aclent_t **, int *, int, int, int);
     81 static int ace4_cmp(nfsace4 *, nfsace4 *);
     82 static int acet_to_ace4(ace_t *, nfsace4 *, int);
     83 static int ace4_to_acet(nfsace4 *, ace_t *, uid_t, gid_t, int, int);
     84 static int validate_idmapping(utf8string *, uid_t, int, int, int);
     85 static int u8s_mapped_to_nobody(utf8string *, uid_t, int);
     86 static void ace4_mask_to_acet_mask(acemask4, uint32_t *);
     87 static void acet_mask_to_ace4_mask(uint32_t, acemask4 *);
     88 static void ace4_flags_to_acet_flags(aceflag4, uint16_t *);
     89 static void acet_flags_to_ace4_flags(uint16_t, aceflag4 *);
     90 
     91 /*
     92  * The following two functions check and set ACE4_SYNCRONIZE, ACE4_WRITE_OWNER,
     93  * ACE4_DELETE and ACE4_WRITE_ATTRIBUTES.
     94  */
     95 static int access_mask_check(nfsace4 *, int, int, int);
     96 static acemask4 access_mask_set(int, int, int, int, int);
     97 
     98 static int nfs4_acl_debug = 0;
     99 
    100 #define	ACL_SYNCHRONIZE_SET_DENY		0x0000001
    101 #define	ACL_SYNCHRONIZE_SET_ALLOW		0x0000002
    102 #define	ACL_SYNCHRONIZE_ERR_DENY		0x0000004
    103 #define	ACL_SYNCHRONIZE_ERR_ALLOW		0x0000008
    104 
    105 #define	ACL_WRITE_OWNER_SET_DENY		0x0000010
    106 #define	ACL_WRITE_OWNER_SET_ALLOW		0x0000020
    107 #define	ACL_WRITE_OWNER_ERR_DENY		0x0000040
    108 #define	ACL_WRITE_OWNER_ERR_ALLOW		0x0000080
    109 
    110 #define	ACL_DELETE_SET_DENY			0x0000100
    111 #define	ACL_DELETE_SET_ALLOW			0x0000200
    112 #define	ACL_DELETE_ERR_DENY			0x0000400
    113 #define	ACL_DELETE_ERR_ALLOW			0x0000800
    114 
    115 #define	ACL_WRITE_ATTRS_OWNER_SET_DENY		0x0001000
    116 #define	ACL_WRITE_ATTRS_OWNER_SET_ALLOW		0x0002000
    117 #define	ACL_WRITE_ATTRS_OWNER_ERR_DENY		0x0004000
    118 #define	ACL_WRITE_ATTRS_OWNER_ERR_ALLOW		0x0008000
    119 
    120 #define	ACL_WRITE_ATTRS_WRITER_SET_DENY		0x0010000
    121 #define	ACL_WRITE_ATTRS_WRITER_SET_ALLOW	0x0020000
    122 #define	ACL_WRITE_ATTRS_WRITER_ERR_DENY		0x0040000
    123 #define	ACL_WRITE_ATTRS_WRITER_ERR_ALLOW	0x0080000
    124 
    125 #define	ACL_WRITE_NAMED_WRITER_SET_DENY		0x0100000
    126 #define	ACL_WRITE_NAMED_WRITER_SET_ALLOW	0x0200000
    127 #define	ACL_WRITE_NAMED_WRITER_ERR_DENY		0x0400000
    128 #define	ACL_WRITE_NAMED_WRITER_ERR_ALLOW	0x0800000
    129 
    130 #define	ACL_READ_NAMED_READER_SET_DENY		0x1000000
    131 #define	ACL_READ_NAMED_READER_SET_ALLOW		0x2000000
    132 #define	ACL_READ_NAMED_READER_ERR_DENY		0x4000000
    133 #define	ACL_READ_NAMED_READER_ERR_ALLOW		0x8000000
    134 
    135 /*
    136  * What we will send the server upon setting an ACL on our client
    137  */
    138 static int nfs4_acl_client_produce =
    139 	(ACL_SYNCHRONIZE_SET_ALLOW |
    140 	ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
    141 	ACL_WRITE_ATTRS_WRITER_SET_DENY);
    142 
    143 /*
    144  * What we will accept upon getting an ACL on our client
    145  */
    146 static int nfs4_acl_client_consume =
    147 	(ACL_WRITE_OWNER_ERR_DENY |
    148 	ACL_WRITE_OWNER_ERR_ALLOW |
    149 	ACL_WRITE_ATTRS_OWNER_ERR_DENY |
    150 	ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
    151 	ACL_WRITE_ATTRS_WRITER_ERR_ALLOW |
    152 	ACL_WRITE_ATTRS_WRITER_SET_DENY);
    153 
    154 /*
    155  * What we will produce as an ACL on a newly created file
    156  */
    157 static int nfs4_acl_server_produce =
    158 	(ACL_SYNCHRONIZE_SET_ALLOW |
    159 	ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
    160 	ACL_WRITE_ATTRS_WRITER_SET_DENY);
    161 
    162 /*
    163  * What we will accept upon setting an ACL on our server
    164  */
    165 static int nfs4_acl_server_consume =
    166 	(ACL_SYNCHRONIZE_ERR_DENY |
    167 	ACL_DELETE_ERR_DENY |
    168 	ACL_WRITE_OWNER_ERR_DENY |
    169 	ACL_WRITE_OWNER_ERR_ALLOW |
    170 	ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
    171 	ACL_WRITE_ATTRS_OWNER_ERR_DENY |
    172 	ACL_WRITE_ATTRS_WRITER_SET_DENY |
    173 	ACL_WRITE_ATTRS_WRITER_ERR_ALLOW |
    174 	ACL_WRITE_NAMED_WRITER_ERR_DENY |
    175 	ACL_READ_NAMED_READER_ERR_DENY);
    176 
    177 static kmem_cache_t *nfs4_ace4vals_cache = NULL;
    178 static kmem_cache_t *nfs4_ace4_list_cache = NULL;
    179 
    180 static int
    181 ace4vals_compare(const void *va, const void *vb)
    182 {
    183 	const ace4vals_t *a = va, *b = vb;
    184 
    185 	if ((a->key == NULL) && (b->key == NULL))
    186 		return (0);
    187 	else if (a->key == NULL)
    188 		return (-1);
    189 	else if (b->key == NULL)
    190 		return (1);
    191 
    192 	return (utf8_compare(a->key, b->key));
    193 }
    194 
    195 /*ARGSUSED*/
    196 static int
    197 nfs4_ace4_list_construct(void *voidp, void *arg, int kmem_flags)
    198 {
    199 	ace4_list_t *a4l = voidp;
    200 
    201 	avl_create(&a4l->user, ace4vals_compare, sizeof (ace4vals_t),
    202 	    offsetof(ace4vals_t, avl));
    203 	avl_create(&a4l->group, ace4vals_compare, sizeof (ace4vals_t),
    204 	    offsetof(ace4vals_t, avl));
    205 	return (0);
    206 }
    207 
    208 /*ARGSUSED*/
    209 static void
    210 nfs4_ace4_list_destroy(void *voidp, void *arg)
    211 {
    212 	ace4_list_t *a4l = voidp;
    213 
    214 	avl_destroy(&a4l->user);
    215 	avl_destroy(&a4l->group);
    216 }
    217 
    218 void
    219 nfs4_acl_init(void)
    220 {
    221 	nfs4_ace4vals_cache = kmem_cache_create("nfs4_ace4vals_cache",
    222 	    sizeof (ace4vals_t), 0,
    223 	    NULL, NULL,
    224 	    NULL, NULL,
    225 	    NULL,
    226 	    0);
    227 	nfs4_ace4_list_cache = kmem_cache_create("nfs4_ace4_list_cache",
    228 	    sizeof (ace4_list_t), 0,
    229 	    nfs4_ace4_list_construct, nfs4_ace4_list_destroy,
    230 	    NULL, NULL,
    231 	    NULL,
    232 	    0);
    233 }
    234 
    235 void
    236 vs_acet_destroy(vsecattr_t *vsp)
    237 {
    238 	if (vsp->vsa_mask != (VSA_ACE | VSA_ACECNT))
    239 		return;
    240 
    241 	if ((vsp->vsa_aclentp != NULL) &&
    242 	    (vsp->vsa_aclcnt > 0) &&
    243 	    (vsp->vsa_mask & VSA_ACE) &&
    244 	    (vsp->vsa_mask & VSA_ACECNT))
    245 		kmem_free(vsp->vsa_aclentp,
    246 		    vsp->vsa_aclcnt * sizeof (ace_t));
    247 
    248 	vsp->vsa_aclentp = NULL;
    249 	vsp->vsa_aclcnt = 0;
    250 }
    251 
    252 void
    253 vs_ace4_destroy(vsecattr_t *vsp)
    254 {
    255 	nfsace4 *ace4;
    256 	int i;
    257 
    258 	if (vsp->vsa_mask != (VSA_ACE | VSA_ACECNT))
    259 		return;
    260 
    261 	if ((vsp->vsa_aclentp != NULL) &&
    262 	    (vsp->vsa_aclcnt > 0) &&
    263 	    (vsp->vsa_mask & VSA_ACE) &&
    264 	    (vsp->vsa_mask & VSA_ACECNT)) {
    265 		for (i = 0; i < vsp->vsa_aclcnt; i++) {
    266 			ace4 = (nfsace4 *)vsp->vsa_aclentp + i;
    267 			if ((ace4->who.utf8string_len > 0) &&
    268 			    (ace4->who.utf8string_val != NULL))
    269 				kmem_free(ace4->who.utf8string_val,
    270 				    ace4->who.utf8string_len);
    271 
    272 			ace4->who.utf8string_val = NULL;
    273 			ace4->who.utf8string_len = 0;
    274 		}
    275 
    276 		kmem_free(vsp->vsa_aclentp,
    277 		    vsp->vsa_aclcnt * sizeof (nfsace4));
    278 	}
    279 
    280 	vsp->vsa_aclentp = NULL;
    281 	vsp->vsa_aclcnt = 0;
    282 }
    283 
    284 void
    285 vs_aent_destroy(vsecattr_t *vsp)
    286 {
    287 	if (vsp->vsa_mask & (VSA_ACE | VSA_ACECNT))
    288 		return;
    289 
    290 	if ((vsp->vsa_aclentp != NULL) &&
    291 	    (vsp->vsa_aclcnt > 0) &&
    292 	    (vsp->vsa_mask & VSA_ACL) &&
    293 	    (vsp->vsa_mask & VSA_ACLCNT))
    294 		kmem_free(vsp->vsa_aclentp,
    295 		    vsp->vsa_aclcnt * sizeof (aclent_t));
    296 	if ((vsp->vsa_dfaclentp != NULL) &&
    297 	    (vsp->vsa_dfaclcnt > 0) &&
    298 	    (vsp->vsa_mask & VSA_DFACL) &&
    299 	    (vsp->vsa_mask & VSA_DFACLCNT))
    300 		kmem_free(vsp->vsa_dfaclentp,
    301 		    vsp->vsa_dfaclcnt * sizeof (aclent_t));
    302 
    303 	vsp->vsa_aclentp = NULL;
    304 	vsp->vsa_aclcnt = 0;
    305 
    306 	vsp->vsa_dfaclentp = NULL;
    307 	vsp->vsa_aclcnt = 0;
    308 }
    309 
    310 /*
    311  * free all data associated with an ace4_list
    312  */
    313 static void
    314 ace4_list_free(ace4_list_t *a4l)
    315 {
    316 	ace4vals_t *node;
    317 	void *cookie;
    318 
    319 	if (a4l == NULL)
    320 		return;
    321 
    322 	/* free all nodes, but don't destroy the trees themselves */
    323 	cookie = NULL;
    324 	while ((node = avl_destroy_nodes(&a4l->user, &cookie)) != NULL)
    325 		kmem_cache_free(nfs4_ace4vals_cache, node);
    326 	cookie = NULL;
    327 	while ((node = avl_destroy_nodes(&a4l->group, &cookie)) != NULL)
    328 		kmem_cache_free(nfs4_ace4vals_cache, node);
    329 
    330 	/* free the container itself */
    331 	kmem_cache_free(nfs4_ace4_list_cache, a4l);
    332 }
    333 
    334 static void
    335 ace4vals_init(ace4vals_t *vals, utf8string *key)
    336 {
    337 	bzero(vals, sizeof (*vals));
    338 	vals->allowed = ACE4_MASK_UNDEFINED;
    339 	vals->denied = ACE4_MASK_UNDEFINED;
    340 	vals->mask = ACE4_MASK_UNDEFINED;
    341 	vals->key = key;
    342 }
    343 
    344 static void
    345 ace4_list_init(ace4_list_t *a4l, int dfacl_flag)
    346 {
    347 	ace4vals_init(&a4l->user_obj, NULL);
    348 	ace4vals_init(&a4l->group_obj, NULL);
    349 	ace4vals_init(&a4l->other_obj, NULL);
    350 	a4l->numusers = 0;
    351 	a4l->numgroups = 0;
    352 	a4l->acl_mask = 0;
    353 	a4l->hasmask = 0;
    354 	a4l->state = ace4_unused;
    355 	a4l->seen = 0;
    356 	a4l->dfacl_flag = dfacl_flag;
    357 }
    358 
    359 /*
    360  * Make an initial pass over an array of aclent_t's.  Gather
    361  * information such as an ACL_MASK (if any), number of users,
    362  * number of groups, and whether the array needs to be sorted.
    363  */
    364 static int
    365 ln_aent_preprocess(aclent_t *aclent, int n,
    366     int *hasmask, o_mode_t *mask,
    367     int *numuser, int *numgroup, int *needsort)
    368 {
    369 	int error = 0;
    370 	int i;
    371 	int curtype = 0;
    372 
    373 	*hasmask = 0;
    374 	*mask = 07;
    375 	*needsort = 0;
    376 	*numuser = 0;
    377 	*numgroup = 0;
    378 
    379 	for (i = 0; i < n; i++) {
    380 		if (aclent[i].a_type < curtype)
    381 			*needsort = 1;
    382 		else if (aclent[i].a_type > curtype)
    383 			curtype = aclent[i].a_type;
    384 		if (aclent[i].a_type & USER)
    385 			(*numuser)++;
    386 		if (aclent[i].a_type & (GROUP | GROUP_OBJ))
    387 			(*numgroup)++;
    388 		if (aclent[i].a_type & CLASS_OBJ) {
    389 			if (*hasmask) {
    390 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    391 				    "ln_aent_preprocess: multiple CLASS_OBJs "
    392 				    "(masks) found"));
    393 				error = EINVAL;
    394 				goto out;
    395 			} else {
    396 				*hasmask = 1;
    397 				*mask = aclent[i].a_perm;
    398 			}
    399 		}
    400 	}
    401 
    402 	if ((! *hasmask) && (*numuser + *numgroup > 1)) {
    403 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    404 		    "ln_aent_preprocess: no CLASS_OBJs "
    405 		    "(masks) found"));
    406 		error = EINVAL;
    407 		goto out;
    408 	}
    409 
    410 out:
    411 	return (error);
    412 }
    413 
    414 static acemask4
    415 access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow,
    416     int isserver)
    417 {
    418 	acemask4 access_mask = 0;
    419 	int nfs4_acl_produce;
    420 	int synchronize_set = 0, write_owner_set = 0;
    421 	int delete_set = 0, write_attrs_set = 0;
    422 	int read_named_set = 0, write_named_set = 0;
    423 
    424 	if (isserver)
    425 		nfs4_acl_produce = nfs4_acl_server_produce;
    426 	else
    427 		nfs4_acl_produce = nfs4_acl_client_produce;
    428 
    429 	if (isallow) {
    430 		synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW;
    431 		write_owner_set = ACL_WRITE_OWNER_SET_ALLOW;
    432 		delete_set = ACL_DELETE_SET_ALLOW;
    433 		if (hasreadperm)
    434 			read_named_set = ACL_READ_NAMED_READER_SET_ALLOW;
    435 		if (haswriteperm)
    436 			write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
    437 		if (isowner)
    438 			write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
    439 		else if (haswriteperm)
    440 			write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
    441 	} else {
    442 		synchronize_set = ACL_SYNCHRONIZE_SET_DENY;
    443 		write_owner_set = ACL_WRITE_OWNER_SET_DENY;
    444 		delete_set = ACL_DELETE_SET_DENY;
    445 		if (hasreadperm)
    446 			read_named_set = ACL_READ_NAMED_READER_SET_DENY;
    447 		if (haswriteperm)
    448 			write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY;
    449 		if (isowner)
    450 			write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY;
    451 		else if (haswriteperm)
    452 			write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY;
    453 		else
    454 			/*
    455 			 * If the entity is not the owner and does not
    456 			 * have write permissions ACE4_WRITE_ATTRIBUTES will
    457 			 * always go in the DENY ACE.
    458 			 */
    459 			access_mask |= ACE4_WRITE_ATTRIBUTES;
    460 	}
    461 
    462 	if (nfs4_acl_produce & synchronize_set)
    463 		access_mask |= ACE4_SYNCHRONIZE;
    464 	if (nfs4_acl_produce & write_owner_set)
    465 		access_mask |= ACE4_WRITE_OWNER;
    466 	if (nfs4_acl_produce & delete_set)
    467 		access_mask |= ACE4_DELETE;
    468 	if (nfs4_acl_produce & write_attrs_set)
    469 		access_mask |= ACE4_WRITE_ATTRIBUTES;
    470 	if (nfs4_acl_produce & read_named_set)
    471 		access_mask |= ACE4_READ_NAMED_ATTRS;
    472 	if (nfs4_acl_produce & write_named_set)
    473 		access_mask |= ACE4_WRITE_NAMED_ATTRS;
    474 
    475 	return (access_mask);
    476 }
    477 
    478 /*
    479  * Given an nfsace4 (presumably an ALLOW entry), make a
    480  * corresponding DENY entry at the address given.
    481  */
    482 static void
    483 ace4_make_deny(nfsace4 *allow, nfsace4 *deny, int isdir, int isowner,
    484     int isserver)
    485 {
    486 	bcopy(allow, deny, sizeof (nfsace4));
    487 
    488 	(void) utf8_copy(&allow->who, &deny->who);
    489 
    490 	deny->type = ACE4_ACCESS_DENIED_ACE_TYPE;
    491 	deny->access_mask ^= ACE4_POSIX_SUPPORTED_BITS;
    492 	if (isdir)
    493 		deny->access_mask ^= ACE4_DELETE_CHILD;
    494 
    495 	deny->access_mask &= ~(ACE4_SYNCHRONIZE | ACE4_WRITE_OWNER |
    496 	    ACE4_DELETE | ACE4_WRITE_ATTRIBUTES | ACE4_READ_NAMED_ATTRS |
    497 	    ACE4_WRITE_NAMED_ATTRS);
    498 	deny->access_mask |= access_mask_set((allow->access_mask &
    499 	    ACE4_WRITE_DATA), (allow->access_mask & ACE4_READ_DATA), isowner,
    500 	    FALSE, isserver);
    501 }
    502 
    503 /*
    504  * Given an o_mode_t, convert it into an access_mask as used
    505  * by nfsace4, assuming aclent_t -> nfsace4 semantics.
    506  */
    507 static acemask4
    508 mode_to_ace4_access(o_mode_t mode, int isdir, int isowner, int isallow,
    509     int isserver)
    510 {
    511 	acemask4 access = 0;
    512 	int haswriteperm = 0;
    513 	int hasreadperm = 0;
    514 
    515 	if (isallow) {
    516 		haswriteperm = (mode & 02);
    517 		hasreadperm = (mode & 04);
    518 	} else {
    519 		haswriteperm = !(mode & 02);
    520 		hasreadperm = !(mode & 04);
    521 	}
    522 
    523 	/*
    524 	 * The following call takes care of correctly setting the following
    525 	 * mask bits in the access_mask:
    526 	 * ACE4_SYNCHRONIZE, ACE4_WRITE_OWNER, ACE4_DELETE,
    527 	 * ACE4_WRITE_ATTRIBUTES, ACE4_WRITE_NAMED_ATTRS, ACE4_READ_NAMED_ATTRS
    528 	 */
    529 	access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow,
    530 	    isserver);
    531 
    532 	if (isallow) {
    533 		access |= ACE4_READ_ACL | ACE4_READ_ATTRIBUTES;
    534 		if (isowner)
    535 			access |= ACE4_WRITE_ACL;
    536 	} else {
    537 		if (! isowner)
    538 			access |= ACE4_WRITE_ACL;
    539 	}
    540 
    541 	/* read */
    542 	if (mode & 04) {
    543 		access |= ACE4_READ_DATA;
    544 	}
    545 	/* write */
    546 	if (mode & 02) {
    547 		access |= ACE4_WRITE_DATA |
    548 		    ACE4_APPEND_DATA;
    549 		if (isdir)
    550 			access |= ACE4_DELETE_CHILD;
    551 	}
    552 	/* exec */
    553 	if (mode & 01) {
    554 		access |= ACE4_EXECUTE;
    555 	}
    556 
    557 	return (access);
    558 }
    559 
    560 /*
    561  * Convert an array of aclent_t into an array of nfsace4 entries,
    562  * following POSIX draft -> nfsv4 conversion semantics as outlined in
    563  * the IETF draft.
    564  */
    565 static int
    566 ln_aent_to_ace4(aclent_t *aclent, int n, nfsace4 **acepp, int *rescount,
    567     int isdir, int isserver)
    568 {
    569 	int error = 0;
    570 	o_mode_t mask;
    571 	int numuser, numgroup, needsort;
    572 	int resultsize = 0;
    573 	int i, groupi = 0, skip;
    574 	nfsace4 *acep, *result = NULL;
    575 	int hasmask;
    576 
    577 	error = ln_aent_preprocess(aclent, n, &hasmask, &mask,
    578 	    &numuser, &numgroup, &needsort);
    579 	if (error != 0)
    580 		goto out;
    581 
    582 	/* allow + deny for each aclent */
    583 	resultsize = n * 2;
    584 	if (hasmask) {
    585 		/*
    586 		 * stick extra deny on the group_obj and on each
    587 		 * user|group for the mask (the group_obj was added
    588 		 * into the count for numgroup)
    589 		 */
    590 		resultsize += numuser + numgroup;
    591 		/* ... and don't count the mask itself */
    592 		resultsize -= 2;
    593 	}
    594 
    595 	/* sort the source if necessary */
    596 	if (needsort)
    597 		ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls);
    598 
    599 	result = acep = kmem_zalloc(resultsize * sizeof (nfsace4), KM_SLEEP);
    600 
    601 	for (i = 0; i < n; i++) {
    602 		/*
    603 		 * don't process CLASS_OBJ (mask); mask was grabbed in
    604 		 * ln_aent_preprocess()
    605 		 */
    606 		if (aclent[i].a_type & CLASS_OBJ)
    607 			continue;
    608 
    609 		/* If we need an ACL_MASK emulator, prepend it now */
    610 		if ((hasmask) &&
    611 		    (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) {
    612 			acep->type = ACE4_ACCESS_DENIED_ACE_TYPE;
    613 			acep->flag = 0;
    614 			if (aclent[i].a_type & GROUP_OBJ) {
    615 				(void) str_to_utf8(ACE4_WHO_GROUP, &acep->who);
    616 				acep->flag |= ACE4_IDENTIFIER_GROUP;
    617 				error = 0;
    618 			} else if (aclent[i].a_type & USER) {
    619 				error = nfs_idmap_uid_str(aclent[i].a_id,
    620 				    &acep->who, isserver);
    621 			} else {
    622 				error = nfs_idmap_gid_str(aclent[i].a_id,
    623 				    &acep->who, isserver);
    624 				acep->flag |= ACE4_IDENTIFIER_GROUP;
    625 			}
    626 			if (error != 0) {
    627 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    628 				    "ln_aent_to_ace4: idmap translate "
    629 				    "failed with %d", error));
    630 				goto out;
    631 			}
    632 			if (aclent[i].a_type & ACL_DEFAULT) {
    633 				acep->flag |= ACE4_INHERIT_ONLY_ACE |
    634 				    ACE4_FILE_INHERIT_ACE |
    635 				    ACE4_DIRECTORY_INHERIT_ACE;
    636 			}
    637 			/*
    638 			 * Set the access mask for the prepended deny
    639 			 * ace.  To do this, we invert the mask (found
    640 			 * in ln_aent_preprocess()) then convert it to an
    641 			 * DENY ace access_mask.
    642 			 */
    643 			acep->access_mask = mode_to_ace4_access((mask ^ 07),
    644 			    isdir, 0, 0, isserver);
    645 			acep += 1;
    646 		}
    647 
    648 		/* handle a_perm -> access_mask */
    649 		acep->access_mask = mode_to_ace4_access(aclent[i].a_perm,
    650 		    isdir, aclent[i].a_type & USER_OBJ, 1, isserver);
    651 
    652 		/* emulate a default aclent */
    653 		if (aclent[i].a_type & ACL_DEFAULT) {
    654 			acep->flag |= ACE4_INHERIT_ONLY_ACE |
    655 			    ACE4_FILE_INHERIT_ACE |
    656 			    ACE4_DIRECTORY_INHERIT_ACE;
    657 		}
    658 
    659 		/*
    660 		 * handle a_perm and a_id
    661 		 *
    662 		 * this must be done last, since it involves the
    663 		 * corresponding deny aces, which are handled
    664 		 * differently for each different a_type.
    665 		 */
    666 		if (aclent[i].a_type & USER_OBJ) {
    667 			(void) str_to_utf8(ACE4_WHO_OWNER, &acep->who);
    668 			ace4_make_deny(acep, acep + 1, isdir, TRUE, isserver);
    669 			acep += 2;
    670 		} else if (aclent[i].a_type & USER) {
    671 			error = nfs_idmap_uid_str(aclent[i].a_id, &acep->who,
    672 			    isserver);
    673 			if (error != 0) {
    674 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    675 				    "ln_aent_to_ace4: uid idmap failed "
    676 				    "with error %d", error));
    677 				goto out;
    678 			}
    679 			ace4_make_deny(acep, acep + 1, isdir, FALSE, isserver);
    680 			acep += 2;
    681 		} else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) {
    682 			if (aclent[i].a_type & GROUP_OBJ) {
    683 				(void) str_to_utf8(ACE4_WHO_GROUP, &acep->who);
    684 				error = 0;
    685 			} else {
    686 				error = nfs_idmap_gid_str(aclent[i].a_id,
    687 				    &acep->who, isserver);
    688 			}
    689 			if (error != 0) {
    690 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    691 				    "ln_aent_to_ace4: gid idmap failed "
    692 				    "with error %d", error));
    693 				goto out;
    694 			}
    695 			acep->flag |= ACE4_IDENTIFIER_GROUP;
    696 			/*
    697 			 * Set the corresponding deny for the group ace.
    698 			 *
    699 			 * The deny aces go after all of the groups, unlike
    700 			 * everything else, where they immediately follow
    701 			 * the allow ace.
    702 			 *
    703 			 * We calculate "skip", the number of slots to
    704 			 * skip ahead for the deny ace, here.
    705 			 *
    706 			 * The pattern is:
    707 			 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
    708 			 * thus, skip is
    709 			 * (2 * numgroup) - 1 - groupi
    710 			 * (2 * numgroup) to account for MD + A
    711 			 * - 1 to account for the fact that we're on the
    712 			 * access (A), not the mask (MD)
    713 			 * - groupi to account for the fact that we have
    714 			 * passed up groupi number of MD's.
    715 			 */
    716 			skip = (2 * numgroup) - 1 - groupi;
    717 			ace4_make_deny(acep, acep + skip, isdir, FALSE,
    718 			    isserver);
    719 			/*
    720 			 * If we just did the last group, skip acep past
    721 			 * all of the denies; else, just move ahead one.
    722 			 */
    723 			if (++groupi >= numgroup)
    724 				acep += numgroup + 1;
    725 			else
    726 				acep += 1;
    727 		} else if (aclent[i].a_type & OTHER_OBJ) {
    728 			(void) str_to_utf8(ACE4_WHO_EVERYONE, &acep->who);
    729 			ace4_make_deny(acep, acep + 1, isdir, FALSE, isserver);
    730 			acep += 2;
    731 		} else {
    732 			NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    733 			    "ln_aent_to_ace4: aclent_t with invalid type: %x",
    734 			    aclent[i].a_type));
    735 			error = EINVAL;
    736 			goto out;
    737 		}
    738 	}
    739 
    740 	*acepp = result;
    741 	*rescount = resultsize;
    742 
    743 out:
    744 
    745 	if (error != 0) {
    746 		if ((result != NULL) && (resultsize > 0)) {
    747 			/* free any embedded "who" strings */
    748 			for (i = 0; i < resultsize; i++) {
    749 				acep = result + i;
    750 				if ((acep->who.utf8string_len > 0) &&
    751 				    (acep->who.utf8string_val != NULL)) {
    752 					kmem_free(acep->who.utf8string_val,
    753 					    acep->who.utf8string_len);
    754 				}
    755 			}
    756 
    757 			/* free the nfsace4 block */
    758 			kmem_free(result, resultsize * sizeof (nfsace4));
    759 		}
    760 	}
    761 
    762 	return (error);
    763 }
    764 
    765 /*
    766  * Convert a POSIX draft ACL (in a vsecattr_t) to an NFSv4 ACL, following
    767  * the semantics of the IETF draft, draft-ietf-nfsv4-acl-mapping-01.txt.
    768  */
    769 int
    770 vs_aent_to_ace4(vsecattr_t *aclentacl, vsecattr_t *vs_ace4,
    771     int isdir, int isserver)
    772 {
    773 	int error = 0;
    774 	nfsace4 *acebuf = NULL;
    775 	int acecnt = 0;
    776 	nfsace4 *dfacebuf = NULL;
    777 	int dfacecnt = 0;
    778 
    779 	/* initialize vs_ace4 in case we can't complete our work */
    780 	vs_ace4->vsa_mask = 0;
    781 	vs_ace4->vsa_aclentp = NULL;
    782 	vs_ace4->vsa_aclcnt = 0;
    783 	vs_ace4->vsa_dfaclentp = NULL;
    784 	vs_ace4->vsa_dfaclcnt = 0;
    785 	vs_ace4->vsa_aclentsz = 0;
    786 
    787 	if (! (aclentacl->vsa_mask & (VSA_ACL | VSA_ACLCNT |
    788 	    VSA_DFACL | VSA_DFACLCNT))) {
    789 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    790 		    "vs_aent_to_ace4: vsa_mask lacking proper mask"));
    791 		error = EINVAL;
    792 		goto out;
    793 	}
    794 
    795 	if ((aclentacl->vsa_aclcnt < 3) &&
    796 	    (aclentacl->vsa_mask & (VSA_ACL | VSA_ACLCNT))) {
    797 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    798 		    "vs_aent_to_ace4: too small vsa_aclcnt, %d",
    799 		    aclentacl->vsa_aclcnt));
    800 		error = EINVAL;
    801 		goto out;
    802 	}
    803 
    804 	if ((aclentacl->vsa_dfaclcnt != 0) && (aclentacl->vsa_dfaclcnt < 3) &&
    805 	    (aclentacl->vsa_mask & (VSA_DFACL | VSA_DFACLCNT))) {
    806 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    807 		    "vs_aent_to_ace4: too small vsa_dfaclcnt, %d",
    808 		    aclentacl->vsa_dfaclcnt));
    809 		error = EINVAL;
    810 		goto out;
    811 	}
    812 
    813 	if (aclentacl->vsa_aclcnt > 0) {
    814 		error = ln_aent_to_ace4(aclentacl->vsa_aclentp,
    815 			aclentacl->vsa_aclcnt, &acebuf, &acecnt,
    816 			    isdir, isserver);
    817 		if (error != 0)
    818 			goto out;
    819 	}
    820 	if (aclentacl->vsa_dfaclcnt > 0) {
    821 		error = ln_aent_to_ace4(aclentacl->vsa_dfaclentp,
    822 			aclentacl->vsa_dfaclcnt, &dfacebuf, &dfacecnt,
    823 			    isdir, isserver);
    824 		if (error != 0)
    825 			goto out;
    826 	}
    827 
    828 	vs_ace4->vsa_aclcnt = acecnt + dfacecnt;
    829 	/* on error, this is freed by vs_ace4_destroy() */
    830 	if (vs_ace4->vsa_aclcnt > 0)
    831 		vs_ace4->vsa_aclentp = kmem_zalloc(vs_ace4->vsa_aclcnt *
    832 		    sizeof (nfsace4), KM_SLEEP);
    833 	/*
    834 	 * When we bcopy the nfsace4's, the result (in vsa_aclentp)
    835 	 * will have its "who.utf8string_val" pointer pointing to the
    836 	 * allocated strings.  Thus, when we free acebuf and dbacebuf,
    837 	 * we don't need to free these strings.
    838 	 */
    839 	if (acecnt > 0)
    840 		bcopy(acebuf, vs_ace4->vsa_aclentp, acecnt * sizeof (nfsace4));
    841 	if (dfacecnt > 0)
    842 		bcopy(dfacebuf, (nfsace4 *) vs_ace4->vsa_aclentp + acecnt,
    843 		    dfacecnt * sizeof (nfsace4));
    844 	vs_ace4->vsa_mask = VSA_ACE | VSA_ACECNT;
    845 
    846 out:
    847 	if (error != 0)
    848 		vs_ace4_destroy(vs_ace4);
    849 
    850 	if (acebuf != NULL)
    851 		kmem_free(acebuf, acecnt * sizeof (nfsace4));
    852 	if (dfacebuf != NULL)
    853 		kmem_free(dfacebuf, dfacecnt * sizeof (nfsace4));
    854 
    855 	return (error);
    856 }
    857 
    858 static int
    859 ace4_mask_to_mode(acemask4 mask, o_mode_t *modep, int isdir)
    860 {
    861 	int error = 0;
    862 	o_mode_t mode = 0;
    863 	acemask4 bits, wantbits;
    864 
    865 	/* read */
    866 	if (mask & ACE4_READ_DATA)
    867 		mode |= 04;
    868 
    869 	/* write */
    870 	wantbits = (ACE4_WRITE_DATA |
    871 	    ACE4_APPEND_DATA);
    872 	if (isdir)
    873 		wantbits |= ACE4_DELETE_CHILD;
    874 	bits = mask & wantbits;
    875 	if (bits != 0) {
    876 		if (bits != wantbits) {
    877 			NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
    878 			    "ace4_mask_to_mode: bad subset of write flags "
    879 			    "%x", bits));
    880 			error = ENOTSUP;
    881 			goto out;
    882 		}
    883 		mode |= 02;
    884 	}
    885 
    886 	/* exec */
    887 	if (mask & ACE4_EXECUTE) {
    888 		mode |= 01;
    889 	}
    890 
    891 	*modep = mode;
    892 
    893 out:
    894 	return (error);
    895 }
    896 
    897 static int
    898 ace4_allow_to_mode(acemask4 mask, o_mode_t *modep, int isdir)
    899 {
    900 	/* ACE4_READ_ACL and ACE4_READ_ATTRIBUTES must both be set */
    901 	if ((mask & (ACE4_READ_ACL | ACE4_READ_ATTRIBUTES)) !=
    902 	    (ACE4_READ_ACL | ACE4_READ_ATTRIBUTES)) {
    903 		return (ENOTSUP);
    904 	}
    905 
    906 	return (ace4_mask_to_mode(mask, modep, isdir));
    907 }
    908 
    909 /*
    910  * Find or create an ace4vals holder for a given id and avl tree.
    911  *
    912  * Note that only one thread will ever touch these avl trees, so
    913  * there is no need for locking.
    914  */
    915 static ace4vals_t *
    916 ace4vals_find(nfsace4 *ace4, avl_tree_t *avl, int *num)
    917 {
    918 	ace4vals_t key, *rc;
    919 	avl_index_t where;
    920 
    921 	key.key = &ace4->who;
    922 	rc = avl_find(avl, &key, &where);
    923 	if (rc != NULL)
    924 		return (rc);
    925 
    926 	/* this memory is freed by ln_ace4_to_aent()->ace4_list_free() */
    927 	rc = kmem_cache_alloc(nfs4_ace4vals_cache, KM_SLEEP);
    928 	ace4vals_init(rc, &ace4->who);
    929 	avl_insert(avl, rc, where);
    930 	(*num)++;
    931 
    932 	return (rc);
    933 }
    934 
    935 static int
    936 access_mask_check(nfsace4 *ace4p, int mask_bit, int isserver, int isowner)
    937 {
    938 	int set_deny, err_deny;
    939 	int set_allow, err_allow;
    940 	int nfs4_acl_consume;
    941 	int haswriteperm, hasreadperm;
    942 
    943 	if (ace4p->type == ACE4_ACCESS_DENIED_ACE_TYPE) {
    944 		haswriteperm = (ace4p->access_mask & ACE4_WRITE_DATA) ? 0 : 1;
    945 		hasreadperm = (ace4p->access_mask & ACE4_READ_DATA) ? 0 : 1;
    946 	} else {
    947 		haswriteperm = (ace4p->access_mask & ACE4_WRITE_DATA) ? 1 : 0;
    948 		hasreadperm = (ace4p->access_mask & ACE4_READ_DATA) ? 1 : 0;
    949 	}
    950 
    951 	if (isserver)
    952 		nfs4_acl_consume = nfs4_acl_server_consume;
    953 	else
    954 		nfs4_acl_consume = nfs4_acl_client_consume;
    955 
    956 	if (mask_bit == ACE4_SYNCHRONIZE) {
    957 		set_deny = ACL_SYNCHRONIZE_SET_DENY;
    958 		err_deny =  ACL_SYNCHRONIZE_ERR_DENY;
    959 		set_allow = ACL_SYNCHRONIZE_SET_ALLOW;
    960 		err_allow = ACL_SYNCHRONIZE_ERR_ALLOW;
    961 	} else if (mask_bit == ACE4_WRITE_OWNER) {
    962 		set_deny = ACL_WRITE_OWNER_SET_DENY;
    963 		err_deny =  ACL_WRITE_OWNER_ERR_DENY;
    964 		set_allow = ACL_WRITE_OWNER_SET_ALLOW;
    965 		err_allow = ACL_WRITE_OWNER_ERR_ALLOW;
    966 	} else if (mask_bit == ACE4_DELETE) {
    967 		set_deny = ACL_DELETE_SET_DENY;
    968 		err_deny =  ACL_DELETE_ERR_DENY;
    969 		set_allow = ACL_DELETE_SET_ALLOW;
    970 		err_allow = ACL_DELETE_ERR_ALLOW;
    971 	} else if (mask_bit == ACE4_WRITE_ATTRIBUTES) {
    972 		if (isowner) {
    973 			set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY;
    974 			err_deny =  ACL_WRITE_ATTRS_OWNER_ERR_DENY;
    975 			set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
    976 			err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW;
    977 		} else if (haswriteperm) {
    978 			set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY;
    979 			err_deny =  ACL_WRITE_ATTRS_WRITER_ERR_DENY;
    980 			set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
    981 			err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW;
    982 		} else {
    983 			if ((ace4p->access_mask & mask_bit) &&
    984 			    (ace4p->type & ACE4_ACCESS_ALLOWED_ACE_TYPE)) {
    985 				return (ENOTSUP);
    986 			}
    987 			return (0);
    988 		}
    989 	} else if (mask_bit == ACE4_READ_NAMED_ATTRS) {
    990 		if (!hasreadperm)
    991 			return (0);
    992 
    993 		set_deny = ACL_READ_NAMED_READER_SET_DENY;
    994 		err_deny = ACL_READ_NAMED_READER_ERR_DENY;
    995 		set_allow = ACL_READ_NAMED_READER_SET_ALLOW;
    996 		err_allow = ACL_READ_NAMED_READER_ERR_ALLOW;
    997 	} else if (mask_bit == ACE4_WRITE_NAMED_ATTRS) {
    998 		if (!haswriteperm)
    999 			return (0);
   1000 
   1001 		set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY;
   1002 		err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY;
   1003 		set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
   1004 		err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW;
   1005 	} else
   1006 		return (EINVAL);
   1007 
   1008 	if (ace4p->type == ACE4_ACCESS_DENIED_ACE_TYPE) {
   1009 		if (nfs4_acl_consume & set_deny) {
   1010 			if (!(ace4p->access_mask & mask_bit)) {
   1011 				return (ENOTSUP);
   1012 			}
   1013 		} else if (nfs4_acl_consume & err_deny) {
   1014 			if (ace4p->access_mask & mask_bit) {
   1015 				return (ENOTSUP);
   1016 			}
   1017 		}
   1018 	} else {
   1019 		/* ACE4_ACCESS_ALLOWED_ACE_TYPE */
   1020 		if (nfs4_acl_consume & set_allow) {
   1021 			if (!(ace4p->access_mask & mask_bit)) {
   1022 				return (ENOTSUP);
   1023 			}
   1024 		} else if (nfs4_acl_consume & err_allow) {
   1025 			if (ace4p->access_mask & mask_bit) {
   1026 				return (ENOTSUP);
   1027 			}
   1028 		}
   1029 	}
   1030 	return (0);
   1031 }
   1032 
   1033 static int
   1034 ace4_to_aent_legal(nfsace4 *ace4p, int isserver)
   1035 {
   1036 	int error = 0;
   1037 	int isowner;
   1038 
   1039 	/* check for NULL who string */
   1040 	if (ace4p->who.utf8string_val == NULL) {
   1041 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1042 		    "ace4_to_aent_legal: NULL who string"));
   1043 		error = EINVAL;
   1044 		goto out;
   1045 	}
   1046 
   1047 	/* only ALLOW or DENY */
   1048 	if ((ace4p->type != ACE4_ACCESS_ALLOWED_ACE_TYPE) &&
   1049 	    (ace4p->type != ACE4_ACCESS_DENIED_ACE_TYPE)) {
   1050 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1051 		    "ace4_to_aent_legal: neither allow nor deny"));
   1052 		error = ENOTSUP;
   1053 		goto out;
   1054 	}
   1055 
   1056 	/* check for invalid flags */
   1057 	if (ace4p->flag & ~(ACE4_VALID_FLAG_BITS)) {
   1058 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1059 		    "ace4_to_aent_legal: invalid flags: %x", ace4p->flag));
   1060 		error = EINVAL;
   1061 		goto out;
   1062 	}
   1063 
   1064 	/* some flags are illegal */
   1065 	if (ace4p->flag & (ACE4_SUCCESSFUL_ACCESS_ACE_FLAG |
   1066 	    ACE4_FAILED_ACCESS_ACE_FLAG |
   1067 	    ACE4_NO_PROPAGATE_INHERIT_ACE)) {
   1068 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1069 		    "ace4_to_aent_legal: illegal flags: %x", ace4p->flag));
   1070 		error = ENOTSUP;
   1071 		goto out;
   1072 	}
   1073 
   1074 	/* check for invalid masks */
   1075 	if (ace4p->access_mask & ~(ACE4_VALID_MASK_BITS)) {
   1076 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1077 		    "ace4_to_aent_legal: invalid mask: %x",
   1078 		    ace4p->access_mask));
   1079 		error = EINVAL;
   1080 		goto out;
   1081 	}
   1082 
   1083 	if ((ace4p->who.utf8string_len == 6) &&
   1084 	    (bcmp(ACE4_WHO_OWNER, ace4p->who.utf8string_val, 6) == 0)) {
   1085 		isowner = 1;
   1086 	} else {
   1087 		isowner = 0;
   1088 	}
   1089 
   1090 	error = access_mask_check(ace4p, ACE4_SYNCHRONIZE, isserver, isowner);
   1091 	if (error)
   1092 		goto out;
   1093 
   1094 	error = access_mask_check(ace4p, ACE4_WRITE_OWNER, isserver, isowner);
   1095 	if (error)
   1096 		goto out;
   1097 
   1098 	error = access_mask_check(ace4p, ACE4_DELETE, isserver, isowner);
   1099 	if (error)
   1100 		goto out;
   1101 
   1102 	error = access_mask_check(ace4p, ACE4_WRITE_ATTRIBUTES, isserver,
   1103 	    isowner);
   1104 	if (error)
   1105 		goto out;
   1106 
   1107 	error = access_mask_check(ace4p, ACE4_READ_NAMED_ATTRS, isserver,
   1108 	    isowner);
   1109 	if (error)
   1110 		goto out;
   1111 
   1112 	error = access_mask_check(ace4p, ACE4_WRITE_NAMED_ATTRS, isserver,
   1113 	    isowner);
   1114 	if (error)
   1115 		goto out;
   1116 
   1117 	/* more detailed checking of masks */
   1118 	if (ace4p->type == ACE4_ACCESS_ALLOWED_ACE_TYPE) {
   1119 		if (! (ace4p->access_mask & ACE4_READ_ATTRIBUTES)) {
   1120 			error = ENOTSUP;
   1121 			goto out;
   1122 		}
   1123 		if ((ace4p->access_mask & ACE4_WRITE_DATA) &&
   1124 		    (! (ace4p->access_mask & ACE4_APPEND_DATA))) {
   1125 			error = ENOTSUP;
   1126 			goto out;
   1127 		}
   1128 		if ((! (ace4p->access_mask & ACE4_WRITE_DATA)) &&
   1129 		    (ace4p->access_mask & ACE4_APPEND_DATA)) {
   1130 			error = ENOTSUP;
   1131 			goto out;
   1132 		}
   1133 	}
   1134 
   1135 	/* ACL enforcement */
   1136 	if ((ace4p->access_mask & ACE4_READ_ACL) &&
   1137 	    (ace4p->type != ACE4_ACCESS_ALLOWED_ACE_TYPE)) {
   1138 		error = ENOTSUP;
   1139 		goto out;
   1140 	}
   1141 	if (ace4p->access_mask & ACE4_WRITE_ACL) {
   1142 		if ((ace4p->type == ACE4_ACCESS_DENIED_ACE_TYPE) &&
   1143 		    (isowner)) {
   1144 			error = ENOTSUP;
   1145 			goto out;
   1146 		}
   1147 		if ((ace4p->type == ACE4_ACCESS_ALLOWED_ACE_TYPE) &&
   1148 		    (! isowner)) {
   1149 			error = ENOTSUP;
   1150 			goto out;
   1151 		}
   1152 	}
   1153 
   1154 out:
   1155 	return (error);
   1156 }
   1157 
   1158 static int
   1159 ace4vals_to_aent(ace4vals_t *vals, aclent_t *dest, ace4_list_t *list,
   1160     uid_t owner, gid_t group, int isdir, int isserver, int just_count)
   1161 {
   1162 	int error;
   1163 	acemask4 flips = ACE4_POSIX_SUPPORTED_BITS;
   1164 
   1165 	if (isdir)
   1166 		flips |= ACE4_DELETE_CHILD;
   1167 	if (vals->allowed != (vals->denied ^ flips)) {
   1168 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1169 		    "ace4vals_to_aent: mis-matched allow/deny pair: %x/%x",
   1170 		    vals->allowed, vals->denied));
   1171 		error = ENOTSUP;
   1172 		goto out;
   1173 	}
   1174 	if ((list->hasmask) && (list->acl_mask != vals->mask) &&
   1175 	    (vals->aent_type & (USER | GROUP | GROUP_OBJ))) {
   1176 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1177 		    "ace4vals_to_aent: entry is missing mask"));
   1178 		error = ENOTSUP;
   1179 		goto out;
   1180 	}
   1181 	error = ace4_allow_to_mode(vals->allowed, &dest->a_perm, isdir);
   1182 	if (error != 0)
   1183 		goto out;
   1184 	dest->a_type = vals->aent_type;
   1185 	if (dest->a_type & (USER | GROUP)) {
   1186 		if (dest->a_type & USER)
   1187 			error = nfs_idmap_str_uid(vals->key, &dest->a_id,
   1188 			    isserver);
   1189 		else
   1190 			error = nfs_idmap_str_gid(vals->key, &dest->a_id,
   1191 			    isserver);
   1192 		if (error != 0) {
   1193 			NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1194 			    "ace4vals_to_aent: idmap failed with %d", error));
   1195 			if (isserver && (error == EPERM))
   1196 				error = NFS4ERR_BADOWNER;
   1197 			goto out;
   1198 		}
   1199 
   1200 		error = validate_idmapping(vals->key, dest->a_id,
   1201 		    (dest->a_type & USER ? 1 : 0), isserver, just_count);
   1202 		if (error != 0) {
   1203 			goto out;
   1204 		}
   1205 	} else if (dest->a_type & USER_OBJ) {
   1206 		dest->a_id = owner;
   1207 	} else if (dest->a_type & GROUP_OBJ) {
   1208 		dest->a_id = group;
   1209 	} else if (dest->a_type & OTHER_OBJ) {
   1210 		dest->a_id = 0;
   1211 	} else {
   1212 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1213 		    "ace4vals_to_aent: dest->a_type invalid: %x "
   1214 		    "(internal error)", dest->a_type));
   1215 		error = EINVAL;
   1216 		goto out;
   1217 	}
   1218 
   1219 out:
   1220 	return (error);
   1221 }
   1222 
   1223 static int
   1224 ace4_list_to_aent(ace4_list_t *list, aclent_t **aclentp, int *aclcnt,
   1225     uid_t owner, gid_t group, int isdir, int isserver, int just_count)
   1226 {
   1227 	int error = 0;
   1228 	aclent_t *aent, *result = NULL;
   1229 	ace4vals_t *vals;
   1230 	int resultcount;
   1231 
   1232 	if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) !=
   1233 	    (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) {
   1234 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1235 			"ace4_list_to_aent: required aclent_t entites "
   1236 			"missing"));
   1237 		error = ENOTSUP;
   1238 		goto out;
   1239 	}
   1240 	if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) {
   1241 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1242 			"ace4_list_to_aent: CLASS_OBJ (mask) missing"));
   1243 		error = ENOTSUP;
   1244 		goto out;
   1245 	}
   1246 
   1247 	resultcount = 3 + list->numusers + list->numgroups;
   1248 	/*
   1249 	 * This must be the same condition as below, when we add the CLASS_OBJ
   1250 	 * (aka ACL mask)
   1251 	 */
   1252 	if ((list->hasmask) || (! list->dfacl_flag))
   1253 		resultcount += 1;
   1254 
   1255 	result = aent = kmem_alloc(resultcount * sizeof (aclent_t), KM_SLEEP);
   1256 
   1257 	/* USER_OBJ */
   1258 	ASSERT(list->user_obj.aent_type & USER_OBJ);
   1259 	error = ace4vals_to_aent(&list->user_obj, aent, list, owner, group,
   1260 	    isdir, isserver, just_count);
   1261 
   1262 	if (error != 0)
   1263 		goto out;
   1264 	++aent;
   1265 	/* USER */
   1266 	vals = NULL;
   1267 	for (vals = avl_first(&list->user); vals != NULL;
   1268 	    vals = AVL_NEXT(&list->user, vals)) {
   1269 		ASSERT(vals->aent_type & USER);
   1270 		error = ace4vals_to_aent(vals, aent, list, owner, group,
   1271 		    isdir, isserver, just_count);
   1272 		if (error != 0)
   1273 			goto out;
   1274 		++aent;
   1275 	}
   1276 	/* GROUP_OBJ */
   1277 	ASSERT(list->group_obj.aent_type & GROUP_OBJ);
   1278 	error = ace4vals_to_aent(&list->group_obj, aent, list, owner, group,
   1279 	    isdir, isserver, just_count);
   1280 	if (error != 0)
   1281 		goto out;
   1282 	++aent;
   1283 	/* GROUP */
   1284 	vals = NULL;
   1285 	for (vals = avl_first(&list->group); vals != NULL;
   1286 	    vals = AVL_NEXT(&list->group, vals)) {
   1287 		ASSERT(vals->aent_type & GROUP);
   1288 		error = ace4vals_to_aent(vals, aent, list, owner, group,
   1289 		    isdir, isserver, just_count);
   1290 		if (error != 0)
   1291 			goto out;
   1292 		++aent;
   1293 	}
   1294 	/*
   1295 	 * CLASS_OBJ (aka ACL_MASK)
   1296 	 *
   1297 	 * An ACL_MASK is not fabricated if the ACL is a default ACL.
   1298 	 * This is to follow UFS's behavior.
   1299 	 */
   1300 	if ((list->hasmask) || (! list->dfacl_flag)) {
   1301 		if (list->hasmask) {
   1302 			acemask4 flips = ACE4_POSIX_SUPPORTED_BITS;
   1303 			if (isdir)
   1304 				flips |= ACE4_DELETE_CHILD;
   1305 			error = ace4_mask_to_mode(list->acl_mask ^ flips,
   1306 			    &aent->a_perm, isdir);
   1307 			if (error != 0)
   1308 				goto out;
   1309 		} else {
   1310 			/* fabricate the ACL_MASK from the group permissions */
   1311 			error = ace4_mask_to_mode(list->group_obj.allowed,
   1312 			    &aent->a_perm, isdir);
   1313 			if (error != 0)
   1314 				goto out;
   1315 		}
   1316 		aent->a_id = 0;
   1317 		aent->a_type = CLASS_OBJ | list->dfacl_flag;
   1318 		++aent;
   1319 	}
   1320 	/* OTHER_OBJ */
   1321 	ASSERT(list->other_obj.aent_type & OTHER_OBJ);
   1322 	error = ace4vals_to_aent(&list->other_obj, aent, list, owner, group,
   1323 	    isdir, isserver, just_count);
   1324 	if (error != 0)
   1325 		goto out;
   1326 	++aent;
   1327 
   1328 	*aclentp = result;
   1329 	*aclcnt = resultcount;
   1330 
   1331 out:
   1332 	if (error != 0) {
   1333 		if (result != NULL)
   1334 			kmem_free(result, resultcount * sizeof (aclent_t));
   1335 	}
   1336 
   1337 	return (error);
   1338 }
   1339 
   1340 /*
   1341  * Convert a list of nfsace4 entries to equivalent regular and default
   1342  * aclent_t lists.  Return error (ENOTSUP) when conversion is not possible.
   1343  */
   1344 static int
   1345 ln_ace4_to_aent(nfsace4 *ace4, int n,
   1346     uid_t owner, gid_t group,
   1347     aclent_t **aclentp, int *aclcnt,
   1348     aclent_t **dfaclentp, int *dfaclcnt,
   1349     int isdir, int isserver, int just_count)
   1350 {
   1351 	int error = 0;
   1352 	nfsace4 *ace4p;
   1353 	acemask4 bits;
   1354 	int i;
   1355 	ace4_list_t *normacl = NULL, *dfacl = NULL, *acl;
   1356 	ace4vals_t *vals;
   1357 
   1358 	*aclentp = NULL;
   1359 	*aclcnt = 0;
   1360 	*dfaclentp = NULL;
   1361 	*dfaclcnt = 0;
   1362 
   1363 	/* we need at least user_obj, group_obj, and other_obj */
   1364 	if (n < 6) {
   1365 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1366 		    "ln_ace4_to_aent: too few nfsace4 entries: %d", n));
   1367 		error = ENOTSUP;
   1368 		goto out;
   1369 	}
   1370 	if (ace4 == NULL) {
   1371 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1372 		    "ln_ace4_to_aent: NULL source"));
   1373 		error = EINVAL;
   1374 		goto out;
   1375 	}
   1376 
   1377 	normacl = kmem_cache_alloc(nfs4_ace4_list_cache, KM_SLEEP);
   1378 	ace4_list_init(normacl, 0);
   1379 	dfacl = kmem_cache_alloc(nfs4_ace4_list_cache, KM_SLEEP);
   1380 	ace4_list_init(dfacl, ACL_DEFAULT);
   1381 
   1382 	/* process every nfsace4... */
   1383 	for (i = 0; i < n; i++) {
   1384 		ace4p = &ace4[i];
   1385 
   1386 		/* rule out certain cases quickly */
   1387 		error = ace4_to_aent_legal(ace4p, isserver);
   1388 		if (error != 0)
   1389 			goto out;
   1390 
   1391 		/*
   1392 		 * Turn off these bits in order to not have to worry about
   1393 		 * them when doing the checks for compliments.
   1394 		 */
   1395 		ace4p->access_mask &= ~(ACE4_WRITE_OWNER | ACE4_DELETE |
   1396 		    ACE4_SYNCHRONIZE | ACE4_WRITE_ATTRIBUTES |
   1397 		    ACE4_READ_NAMED_ATTRS | ACE4_WRITE_NAMED_ATTRS);
   1398 
   1399 		/* see if this should be a regular or default acl */
   1400 		bits = ace4p->flag &
   1401 		    (ACE4_INHERIT_ONLY_ACE |
   1402 		    ACE4_FILE_INHERIT_ACE |
   1403 		    ACE4_DIRECTORY_INHERIT_ACE);
   1404 		if (bits != 0) {
   1405 			/* all or nothing on these inherit bits */
   1406 			if (bits != (ACE4_INHERIT_ONLY_ACE |
   1407 			    ACE4_FILE_INHERIT_ACE |
   1408 			    ACE4_DIRECTORY_INHERIT_ACE)) {
   1409 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1410 				    "ln_ace4_to_aent: bad inherit flags "
   1411 				    "%x", bits));
   1412 				error = ENOTSUP;
   1413 				goto out;
   1414 			}
   1415 			acl = dfacl;
   1416 		} else {
   1417 			acl = normacl;
   1418 		}
   1419 
   1420 		if ((ace4p->who.utf8string_len == 6) &&
   1421 		    (bcmp(ACE4_WHO_OWNER,
   1422 		    ace4p->who.utf8string_val, 6) == 0)) {
   1423 			if (acl->state > ace4_user_obj) {
   1424 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1425 				    "ln_ace4_to_aent: OWNER@ found "
   1426 				    "out of order"));
   1427 				error = ENOTSUP;
   1428 				goto out;
   1429 			}
   1430 			acl->state = ace4_user_obj;
   1431 			acl->seen |= USER_OBJ;
   1432 			vals = &acl->user_obj;
   1433 			vals->aent_type = USER_OBJ | acl->dfacl_flag;
   1434 		} else if ((ace4p->who.utf8string_len == 9) &&
   1435 		    (bcmp(ACE4_WHO_EVERYONE, ace4p->who.utf8string_val, 9)
   1436 		    == 0)) {
   1437 			acl->state = ace4_other_obj;
   1438 			acl->seen |= OTHER_OBJ;
   1439 			vals = &acl->other_obj;
   1440 			vals->aent_type = OTHER_OBJ | acl->dfacl_flag;
   1441 		} else if ((ace4p->who.utf8string_len == 6) &&
   1442 		    (bcmp(ACE4_WHO_GROUP, ace4p->who.utf8string_val, 6) == 0)) {
   1443 			if (acl->state > ace4_group) {
   1444 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1445 				    "ln_ace4_to_aent: group entry found "
   1446 				    "out of order"));
   1447 				error = ENOTSUP;
   1448 				goto out;
   1449 			}
   1450 			acl->seen |= GROUP_OBJ;
   1451 			vals = &acl->group_obj;
   1452 			vals->aent_type = GROUP_OBJ | acl->dfacl_flag;
   1453 			acl->state = ace4_group;
   1454 		} else if (ace4p->flag & ACE4_IDENTIFIER_GROUP) {
   1455 			if (acl->state > ace4_group) {
   1456 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1457 				    "ln_ace4_to_aent: group entry found "
   1458 				    "out of order"));
   1459 				error = ENOTSUP;
   1460 				goto out;
   1461 			}
   1462 			acl->seen |= GROUP;
   1463 			vals = ace4vals_find(ace4p, &acl->group,
   1464 			    &acl->numgroups);
   1465 			vals->aent_type = GROUP | acl->dfacl_flag;
   1466 			acl->state = ace4_group;
   1467 		} else {
   1468 			if (acl->state > ace4_user) {
   1469 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1470 				    "ln_ace4_to_aent: user entry found "
   1471 				    "out of order"));
   1472 				error = ENOTSUP;
   1473 				goto out;
   1474 			}
   1475 			acl->state = ace4_user;
   1476 			acl->seen |= USER;
   1477 			vals = ace4vals_find(ace4p, &acl->user,
   1478 			    &acl->numusers);
   1479 			vals->aent_type = USER | acl->dfacl_flag;
   1480 		}
   1481 		ASSERT(acl->state > ace4_unused);
   1482 
   1483 		if (ace4p->type == ACE4_ACCESS_ALLOWED_ACE_TYPE) {
   1484 			/* no more than one allowed per aclent_t */
   1485 			if (vals->allowed != ACE4_MASK_UNDEFINED) {
   1486 				NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1487 				    "ln_ace4_to_aent: too many ALLOWs "
   1488 				    "for one entity"));
   1489 				error = ENOTSUP;
   1490 				goto out;
   1491 			}
   1492 			vals->allowed = ace4p->access_mask;
   1493 		} else {
   1494 			/*
   1495 			 * it's a DENY; if there was a previous DENY, it
   1496 			 * must have been an ACL_MASK.
   1497 			 */
   1498 			if (vals->denied != ACE4_MASK_UNDEFINED) {
   1499 				/* ACL_MASK is for USER and GROUP only */
   1500 				if ((acl->state != ace4_user) &&
   1501 				    (acl->state != ace4_group)) {
   1502 					NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1503 					    "ln_ace4_to_aent: ACL_MASK-like "
   1504 					    "DENY found on non-user/non-group "
   1505 					    "entity"));
   1506 					error = ENOTSUP;
   1507 					goto out;
   1508 				}
   1509 
   1510 				if (! acl->hasmask) {
   1511 					acl->hasmask = 1;
   1512 					acl->acl_mask = vals->denied;
   1513 				/* check for mismatched ACL_MASK emulations */
   1514 				} else if (acl->acl_mask != vals->denied) {
   1515 					NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1516 					    "ln_ace4_to_aent: ACL_MASK "
   1517 					    "mismatch"));
   1518 					error = ENOTSUP;
   1519 					goto out;
   1520 				}
   1521 				vals->mask = vals->denied;
   1522 			}
   1523 			vals->denied = ace4p->access_mask;
   1524 		}
   1525 	}
   1526 
   1527 	/* done collating; produce the aclent_t lists */
   1528 	if (normacl->state != ace4_unused) {
   1529 		error = ace4_list_to_aent(normacl, aclentp, aclcnt,
   1530 		    owner, group, isdir, isserver, just_count);
   1531 		if (error != 0)
   1532 			goto out;
   1533 	}
   1534 	if (dfacl->state != ace4_unused) {
   1535 		error = ace4_list_to_aent(dfacl, dfaclentp, dfaclcnt,
   1536 		    owner, group, isdir, isserver, just_count);
   1537 		if (error != 0)
   1538 			goto out;
   1539 	}
   1540 
   1541 out:
   1542 	if (normacl != NULL)
   1543 		ace4_list_free(normacl);
   1544 	if (dfacl != NULL)
   1545 		ace4_list_free(dfacl);
   1546 
   1547 	return (error);
   1548 }
   1549 
   1550 /*
   1551  * Convert an NFSv4 ACL (in a vsecattr_t) to a POSIX draft ACL, following
   1552  * the semantics of NFSv4_to_POSIX.html.  Contact fsh-group (at) sun.com to
   1553  * obtain this document.
   1554  */
   1555 int
   1556 vs_ace4_to_aent(vsecattr_t *vs_ace4, vsecattr_t *vs_aent,
   1557     uid_t owner, gid_t group, int isdir, int isserver, int just_count)
   1558 {
   1559 	int error = 0;
   1560 
   1561 	error = ln_ace4_to_aent(vs_ace4->vsa_aclentp, vs_ace4->vsa_aclcnt,
   1562 	    owner, group,
   1563 	    (aclent_t **)&vs_aent->vsa_aclentp, &vs_aent->vsa_aclcnt,
   1564 	    (aclent_t **)&vs_aent->vsa_dfaclentp, &vs_aent->vsa_dfaclcnt,
   1565 	    isdir, isserver, just_count);
   1566 	if (error != 0)
   1567 		goto out;
   1568 
   1569 	vs_aent->vsa_mask = VSA_ACL | VSA_ACLCNT | VSA_DFACL | VSA_DFACLCNT;
   1570 	if ((vs_aent->vsa_aclcnt == 0) && (vs_aent->vsa_dfaclcnt == 0)) {
   1571 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1572 		    "vs_ace4_to_aent: neither ACL nor default ACL found"));
   1573 		error = ENOTSUP;
   1574 		goto out;
   1575 	}
   1576 
   1577 out:
   1578 	if (error != 0) {
   1579 		if (vs_aent != NULL)
   1580 			vs_aent_destroy(vs_aent);
   1581 	}
   1582 
   1583 	return (error);
   1584 }
   1585 
   1586 /*
   1587  * compare two ace4 acls
   1588  */
   1589 
   1590 static int
   1591 ace4_cmp(nfsace4 *a, nfsace4 *b)
   1592 {
   1593 	if (a->type < b->type)
   1594 		return (-1);
   1595 	if (a->type > b->type)
   1596 		return (1);
   1597 	if (a->flag < b->flag)
   1598 		return (-1);
   1599 	if (a->flag > b->flag)
   1600 		return (1);
   1601 	if (a->access_mask < b->access_mask)
   1602 		return (-1);
   1603 	if (a->access_mask > b->access_mask)
   1604 		return (1);
   1605 	return (utf8_compare(&a->who, &b->who));
   1606 }
   1607 
   1608 int
   1609 ln_ace4_cmp(nfsace4 *a, nfsace4* b, int n)
   1610 {
   1611 	int rc;
   1612 	int i;
   1613 
   1614 	for (i = 0; i < n; i++) {
   1615 		rc = ace4_cmp(a + i, b + i);
   1616 		if (rc != 0)
   1617 			return (rc);
   1618 	}
   1619 	return (0);
   1620 }
   1621 
   1622 /*
   1623  * Convert an ace_t to an nfsace4; the primary difference being
   1624  * strings versus integer uid/gids.
   1625  */
   1626 static int
   1627 acet_to_ace4(ace_t *ace, nfsace4 *nfsace4, int isserver)
   1628 {
   1629 	int error = 0;
   1630 
   1631 	if (ace == NULL) {
   1632 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1633 		    "acet_to_ace4: NULL source"));
   1634 		error = EINVAL;
   1635 		goto out;
   1636 	}
   1637 	if (nfsace4 == NULL) {
   1638 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1639 		    "acet_to_ace4: NULL destination"));
   1640 		error = EINVAL;
   1641 		goto out;
   1642 	}
   1643 
   1644 	switch (ace->a_type) {
   1645 	case ACE_ACCESS_ALLOWED_ACE_TYPE:
   1646 		nfsace4->type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
   1647 		break;
   1648 	case ACE_ACCESS_DENIED_ACE_TYPE:
   1649 		nfsace4->type = ACE4_ACCESS_DENIED_ACE_TYPE;
   1650 		break;
   1651 	default:
   1652 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1653 		    "acet_to_ace4: unsupported type: %x", ace->a_type));
   1654 		error = ENOTSUP;
   1655 		break;
   1656 	}
   1657 	if (error != 0)
   1658 		goto out;
   1659 
   1660 	acet_mask_to_ace4_mask(ace->a_access_mask, &nfsace4->access_mask);
   1661 	acet_flags_to_ace4_flags(ace->a_flags, &nfsace4->flag);
   1662 
   1663 	if (ace->a_flags & ACE_GROUP) {
   1664 		nfsace4->flag |= ACE4_IDENTIFIER_GROUP;
   1665 		(void) str_to_utf8(ACE4_WHO_GROUP, &nfsace4->who);
   1666 	} else if (ace->a_flags & ACE_IDENTIFIER_GROUP) {
   1667 		nfsace4->flag |= ACE4_IDENTIFIER_GROUP;
   1668 		error = nfs_idmap_gid_str(ace->a_who, &nfsace4->who, isserver);
   1669 		if (error != 0)
   1670 			NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1671 			    "acet_to_ace4: idmap failed with %d", error));
   1672 	} else if (ace->a_flags & ACE_OWNER) {
   1673 		(void) str_to_utf8(ACE4_WHO_OWNER, &nfsace4->who);
   1674 	} else if (ace->a_flags & ACE_EVERYONE) {
   1675 		(void) str_to_utf8(ACE4_WHO_EVERYONE, &nfsace4->who);
   1676 	} else {
   1677 		error = nfs_idmap_uid_str(ace->a_who, &nfsace4->who, isserver);
   1678 		if (error != 0)
   1679 			NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1680 			    "acet_to_ace4: idmap failed with %d", error));
   1681 	}
   1682 
   1683 out:
   1684 	return (error);
   1685 }
   1686 
   1687 /*
   1688  * Convert an nfsace4 to an ace_t, the primary difference being
   1689  * integer uid/gids versus strings.
   1690  */
   1691 static int
   1692 ace4_to_acet(nfsace4 *nfsace4, ace_t *ace, uid_t owner, gid_t group,
   1693     int isserver, int just_count)
   1694 {
   1695 	int error = 0;
   1696 
   1697 	if (nfsace4 == NULL) {
   1698 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1699 		    "ace4_to_acet: NULL source"));
   1700 		return (EINVAL);
   1701 	}
   1702 	if (ace == NULL) {
   1703 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1704 		    "ace4_to_acet: NULL destination"));
   1705 		return (EINVAL);
   1706 	}
   1707 
   1708 	switch (nfsace4->type) {
   1709 	case ACE4_ACCESS_ALLOWED_ACE_TYPE:
   1710 		ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
   1711 		break;
   1712 	case ACE4_ACCESS_DENIED_ACE_TYPE:
   1713 		ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
   1714 		break;
   1715 	default:
   1716 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1717 		    "ace4_to_acet: unsupported type: %x", nfsace4->type));
   1718 		error = ENOTSUP;
   1719 		break;
   1720 	}
   1721 	if (error != 0)
   1722 		goto out;
   1723 
   1724 	if (nfsace4->flag & ~(ACE4_VALID_FLAG_BITS)) {
   1725 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1726 		    "ace4_to_acet: invalid flags: %x", nfsace4->flag));
   1727 		error = EINVAL;
   1728 		goto out;
   1729 	}
   1730 
   1731 	/* check for invalid masks */
   1732 	if (nfsace4->access_mask & ~(ACE4_VALID_MASK_BITS)) {
   1733 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1734 		    "ace4_to_acet: invalid mask: %x", nfsace4->access_mask));
   1735 		error = EINVAL;
   1736 		goto out;
   1737 	}
   1738 
   1739 	ace4_mask_to_acet_mask(nfsace4->access_mask, &ace->a_access_mask);
   1740 
   1741 	if (nfsace4->flag & ~ACE_NFSV4_SUP_FLAGS) {
   1742 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1743 		    "ace4_to_acet: unsupported flags: %x", nfsace4->flag));
   1744 		error = ENOTSUP;
   1745 		goto out;
   1746 	}
   1747 	ace4_flags_to_acet_flags(nfsace4->flag, &ace->a_flags);
   1748 
   1749 	if ((nfsace4->who.utf8string_len == 6) &&
   1750 	    (bcmp(ACE4_WHO_GROUP,
   1751 	    nfsace4->who.utf8string_val, 6)) == 0) {
   1752 		ace->a_who = group;
   1753 		ace->a_flags |= ACE_GROUP | ACE_IDENTIFIER_GROUP;
   1754 	} else if ((nfsace4->who.utf8string_len == 6) &&
   1755 	    (bcmp(ACE4_WHO_OWNER,
   1756 	    nfsace4->who.utf8string_val, 6) == 0)) {
   1757 		ace->a_flags |= ACE_OWNER;
   1758 		ace->a_who = owner;
   1759 	} else if ((nfsace4->who.utf8string_len == 9) &&
   1760 	    (bcmp(ACE4_WHO_EVERYONE,
   1761 	    nfsace4->who.utf8string_val, 9) == 0)) {
   1762 		ace->a_flags |= ACE_EVERYONE;
   1763 		ace->a_who = 0;
   1764 	} else if (nfsace4->flag & ACE4_IDENTIFIER_GROUP) {
   1765 		ace->a_flags |= ACE_IDENTIFIER_GROUP;
   1766 		error = nfs_idmap_str_gid(&nfsace4->who,
   1767 		    &ace->a_who, isserver);
   1768 		if (error != 0) {
   1769 			NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1770 			    "ace4_to_acet: idmap failed with %d",
   1771 			    error));
   1772 			if (isserver && (error == EPERM))
   1773 				error = NFS4ERR_BADOWNER;
   1774 			goto out;
   1775 		}
   1776 		error = validate_idmapping(&nfsace4->who,
   1777 		    ace->a_who, FALSE, isserver, just_count);
   1778 		if (error != 0)
   1779 			goto out;
   1780 	} else {
   1781 		error = nfs_idmap_str_uid(&nfsace4->who,
   1782 		    &ace->a_who, isserver);
   1783 		if (error != 0) {
   1784 			NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1785 			    "ace4_to_acet: idmap failed with %d",
   1786 			    error));
   1787 			if (isserver && (error == EPERM))
   1788 				error = NFS4ERR_BADOWNER;
   1789 			goto out;
   1790 		}
   1791 		error = validate_idmapping(&nfsace4->who,
   1792 		    ace->a_who, TRUE, isserver, just_count);
   1793 		if (error != 0)
   1794 			goto out;
   1795 	}
   1796 
   1797 out:
   1798 	return (error);
   1799 }
   1800 
   1801 static void
   1802 ace4_mask_to_acet_mask(acemask4 ace4_mask, uint32_t *acet_mask)
   1803 {
   1804 	*acet_mask = 0;
   1805 
   1806 	if (ace4_mask & ACE4_READ_DATA)
   1807 		*acet_mask |= ACE_READ_DATA;
   1808 	if (ace4_mask & ACE4_WRITE_DATA)
   1809 		*acet_mask |= ACE_WRITE_DATA;
   1810 	if (ace4_mask & ACE4_APPEND_DATA)
   1811 		*acet_mask |= ACE_APPEND_DATA;
   1812 	if (ace4_mask & ACE4_READ_NAMED_ATTRS)
   1813 		*acet_mask |= ACE_READ_NAMED_ATTRS;
   1814 	if (ace4_mask & ACE4_WRITE_NAMED_ATTRS)
   1815 		*acet_mask |= ACE_WRITE_NAMED_ATTRS;
   1816 	if (ace4_mask & ACE4_EXECUTE)
   1817 		*acet_mask |= ACE_EXECUTE;
   1818 	if (ace4_mask & ACE4_DELETE_CHILD)
   1819 		*acet_mask |= ACE_DELETE_CHILD;
   1820 	if (ace4_mask & ACE4_READ_ATTRIBUTES)
   1821 		*acet_mask |= ACE_READ_ATTRIBUTES;
   1822 	if (ace4_mask & ACE4_WRITE_ATTRIBUTES)
   1823 		*acet_mask |= ACE_WRITE_ATTRIBUTES;
   1824 	if (ace4_mask & ACE4_DELETE)
   1825 		*acet_mask |= ACE_DELETE;
   1826 	if (ace4_mask & ACE4_READ_ACL)
   1827 		*acet_mask |= ACE_READ_ACL;
   1828 	if (ace4_mask & ACE4_WRITE_ACL)
   1829 		*acet_mask |= ACE_WRITE_ACL;
   1830 	if (ace4_mask & ACE4_WRITE_OWNER)
   1831 		*acet_mask |= ACE_WRITE_OWNER;
   1832 	if (ace4_mask & ACE4_SYNCHRONIZE)
   1833 		*acet_mask |= ACE_SYNCHRONIZE;
   1834 }
   1835 
   1836 static void
   1837 acet_mask_to_ace4_mask(uint32_t acet_mask, acemask4 *ace4_mask)
   1838 {
   1839 	*ace4_mask = 0;
   1840 
   1841 	if (acet_mask & ACE_READ_DATA)
   1842 		*ace4_mask |= ACE4_READ_DATA;
   1843 	if (acet_mask & ACE_WRITE_DATA)
   1844 		*ace4_mask |= ACE4_WRITE_DATA;
   1845 	if (acet_mask & ACE_APPEND_DATA)
   1846 		*ace4_mask |= ACE_APPEND_DATA;
   1847 	if (acet_mask & ACE4_READ_NAMED_ATTRS)
   1848 		*ace4_mask |= ACE_READ_NAMED_ATTRS;
   1849 	if (acet_mask & ACE_WRITE_NAMED_ATTRS)
   1850 		*ace4_mask |= ACE4_WRITE_NAMED_ATTRS;
   1851 	if (acet_mask & ACE_EXECUTE)
   1852 		*ace4_mask |= ACE4_EXECUTE;
   1853 	if (acet_mask & ACE_DELETE_CHILD)
   1854 		*ace4_mask |= ACE4_DELETE_CHILD;
   1855 	if (acet_mask & ACE_READ_ATTRIBUTES)
   1856 		*ace4_mask |= ACE4_READ_ATTRIBUTES;
   1857 	if (acet_mask & ACE_WRITE_ATTRIBUTES)
   1858 		*ace4_mask |= ACE4_WRITE_ATTRIBUTES;
   1859 	if (acet_mask & ACE_DELETE)
   1860 		*ace4_mask |= ACE4_DELETE;
   1861 	if (acet_mask & ACE_READ_ACL)
   1862 		*ace4_mask |= ACE4_READ_ACL;
   1863 	if (acet_mask & ACE_WRITE_ACL)
   1864 		*ace4_mask |= ACE4_WRITE_ACL;
   1865 	if (acet_mask & ACE_WRITE_OWNER)
   1866 		*ace4_mask |= ACE4_WRITE_OWNER;
   1867 	if (acet_mask & ACE_SYNCHRONIZE)
   1868 		*ace4_mask |= ACE4_SYNCHRONIZE;
   1869 }
   1870 
   1871 static void
   1872 ace4_flags_to_acet_flags(aceflag4 ace4_flags, uint16_t *acet_flags)
   1873 {
   1874 	*acet_flags = 0;
   1875 
   1876 	if (ace4_flags & ACE4_FILE_INHERIT_ACE)
   1877 		*acet_flags |= ACE_FILE_INHERIT_ACE;
   1878 	if (ace4_flags & ACE4_DIRECTORY_INHERIT_ACE)
   1879 		*acet_flags |= ACE_DIRECTORY_INHERIT_ACE;
   1880 	if (ace4_flags & ACE4_NO_PROPAGATE_INHERIT_ACE)
   1881 		*acet_flags |= ACE_NO_PROPAGATE_INHERIT_ACE;
   1882 	if (ace4_flags & ACE4_INHERIT_ONLY_ACE)
   1883 		*acet_flags |= ACE_INHERIT_ONLY_ACE;
   1884 	if (ace4_flags & ACE4_SUCCESSFUL_ACCESS_ACE_FLAG)
   1885 		*acet_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
   1886 	if (ace4_flags & ACE4_FAILED_ACCESS_ACE_FLAG)
   1887 		*acet_flags |= ACE_FAILED_ACCESS_ACE_FLAG;
   1888 	/* ACE_IDENTIFIER_GROUP is handled in ace4_to_acet() */
   1889 }
   1890 
   1891 static void
   1892 acet_flags_to_ace4_flags(uint16_t acet_flags, aceflag4 *ace4_flags)
   1893 {
   1894 	*ace4_flags = 0;
   1895 
   1896 	if (acet_flags & ACE_FILE_INHERIT_ACE)
   1897 		*ace4_flags |= ACE4_FILE_INHERIT_ACE;
   1898 	if (acet_flags & ACE_DIRECTORY_INHERIT_ACE)
   1899 		*ace4_flags |= ACE4_DIRECTORY_INHERIT_ACE;
   1900 	if (acet_flags & ACE_NO_PROPAGATE_INHERIT_ACE)
   1901 		*ace4_flags |= ACE4_NO_PROPAGATE_INHERIT_ACE;
   1902 	if (acet_flags & ACE_INHERIT_ONLY_ACE)
   1903 		*ace4_flags |= ACE4_INHERIT_ONLY_ACE;
   1904 	if (acet_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG)
   1905 		*ace4_flags |= ACE4_SUCCESSFUL_ACCESS_ACE_FLAG;
   1906 	if (acet_flags & ACE_FAILED_ACCESS_ACE_FLAG)
   1907 		*ace4_flags |= ACE4_FAILED_ACCESS_ACE_FLAG;
   1908 	/* ACE4_IDENTIFIER_GROUP is handled in acet_to_ace4() */
   1909 }
   1910 
   1911 int
   1912 vs_ace4_to_acet(vsecattr_t *vs_ace4, vsecattr_t *vs_acet,
   1913     uid_t owner, gid_t group, int isserver, int just_count)
   1914 {
   1915 	int error;
   1916 	int i;
   1917 
   1918 	if ((vs_ace4->vsa_mask & (VSA_ACE | VSA_ACECNT)) !=
   1919 	    (VSA_ACE | VSA_ACECNT))
   1920 		return (EINVAL);
   1921 	if (vs_ace4->vsa_aclcnt < 0)
   1922 		return (EINVAL);
   1923 	if ((vs_ace4->vsa_aclcnt == 0) || (vs_ace4->vsa_aclentp == NULL))
   1924 		return (0);
   1925 
   1926 	if (vs_ace4->vsa_aclcnt > 0) {
   1927 		vs_acet->vsa_aclentp = kmem_alloc(vs_ace4->vsa_aclcnt *
   1928 		    sizeof (ace_t), KM_SLEEP);
   1929 		vs_acet->vsa_aclentsz = vs_ace4->vsa_aclcnt * sizeof (ace_t);
   1930 	} else
   1931 		vs_acet->vsa_aclentp = NULL;
   1932 	vs_acet->vsa_aclcnt = vs_ace4->vsa_aclcnt;
   1933 	vs_acet->vsa_mask = VSA_ACE | VSA_ACECNT;
   1934 
   1935 	for (i = 0; i < vs_ace4->vsa_aclcnt; i++) {
   1936 		error = ace4_to_acet((nfsace4 *)(vs_ace4->vsa_aclentp) + i,
   1937 		    (ace_t *)(vs_acet->vsa_aclentp) + i, owner, group,
   1938 		    isserver, just_count);
   1939 		if (error != 0)
   1940 			goto out;
   1941 	}
   1942 
   1943 out:
   1944 	if (error != 0)
   1945 		vs_acet_destroy(vs_acet);
   1946 
   1947 	return (error);
   1948 }
   1949 
   1950 int
   1951 vs_acet_to_ace4(vsecattr_t *vs_acet, vsecattr_t *vs_ace4,
   1952     int isserver)
   1953 {
   1954 	int error = 0;
   1955 	int i;
   1956 
   1957 	if (! (vs_acet->vsa_mask & VSA_ACE)) {
   1958 		NFS4_DEBUG(nfs4_acl_debug, (CE_NOTE,
   1959 		    "vs_acet_to_ace4: VSA_ACE missing from mask"));
   1960 		return (EINVAL);
   1961 	}
   1962 
   1963 	if (vs_acet->vsa_aclcnt > 0)
   1964 		vs_ace4->vsa_aclentp = kmem_zalloc(vs_acet->vsa_aclcnt *
   1965 		    sizeof (nfsace4), KM_SLEEP);
   1966 	else
   1967 		vs_ace4->vsa_aclentp = NULL;
   1968 	vs_ace4->vsa_aclcnt = vs_acet->vsa_aclcnt;
   1969 	vs_ace4->vsa_mask = VSA_ACE | VSA_ACECNT;
   1970 
   1971 	for (i = 0; i < vs_acet->vsa_aclcnt; i++) {
   1972 		error = acet_to_ace4((ace_t *)(vs_acet->vsa_aclentp) + i,
   1973 		    (nfsace4 *)(vs_ace4->vsa_aclentp) + i, isserver);
   1974 		if (error != 0)
   1975 			goto out;
   1976 	}
   1977 
   1978 out:
   1979 	if (error != 0)
   1980 		vs_ace4_destroy(vs_ace4);
   1981 
   1982 	return (error);
   1983 }
   1984 
   1985 void
   1986 nfs4_acl_fill_cache(rnode4_t *rp, vsecattr_t *vsap)
   1987 {
   1988 	size_t aclsize;
   1989 	vsecattr_t *rvsap;
   1990 	nfsace4 *tmp_ace4, *ace4;
   1991 	int i;
   1992 
   1993 	mutex_enter(&rp->r_statelock);
   1994 	if (rp->r_secattr != NULL)
   1995 		rvsap = rp->r_secattr;
   1996 	else {
   1997 		rvsap = kmem_zalloc(sizeof (*rvsap), KM_NOSLEEP);
   1998 		if (rvsap == NULL) {
   1999 			mutex_exit(&rp->r_statelock);
   2000 			return;
   2001 		}
   2002 		rp->r_secattr = rvsap;
   2003 	}
   2004 
   2005 	if (vsap->vsa_mask & VSA_ACE) {
   2006 		if (rvsap->vsa_aclentp != NULL) {
   2007 			if (rvsap->vsa_aclcnt != vsap->vsa_aclcnt) {
   2008 				vs_ace4_destroy(rvsap);
   2009 				rvsap->vsa_aclentp = NULL;
   2010 			} else {
   2011 				/*
   2012 				 * The counts are equal so we don't have to
   2013 				 * destroy the acl entries because we'd only
   2014 				 * have to re-allocate them, but we do have to
   2015 				 * destroy all of the who utf8strings.
   2016 				 * The acl that we are now filling the cache
   2017 				 * with may have the same amount of entries as
   2018 				 * what is currently cached, but those entries
   2019 				 * may not be the same.
   2020 				 */
   2021 				ace4 = (nfsace4 *) rvsap->vsa_aclentp;
   2022 				for (i = 0; i < rvsap->vsa_aclcnt; i++) {
   2023 					if (ace4[i].who.utf8string_val != NULL)
   2024 						kmem_free(
   2025 						    ace4[i].who.utf8string_val,
   2026 						    ace4[i].who.utf8string_len);
   2027 				}
   2028 			}
   2029 		}
   2030 		if (vsap->vsa_aclcnt > 0) {
   2031 			aclsize = vsap->vsa_aclcnt * sizeof (nfsace4);
   2032 
   2033 			if (rvsap->vsa_aclentp == NULL) {
   2034 				rvsap->vsa_aclentp = kmem_alloc(aclsize,
   2035 				    KM_SLEEP);
   2036 			}
   2037 
   2038 			bcopy(vsap->vsa_aclentp, rvsap->vsa_aclentp, aclsize);
   2039 
   2040 			tmp_ace4 = (nfsace4 *) vsap->vsa_aclentp;
   2041 			ace4 = (nfsace4 *) rvsap->vsa_aclentp;
   2042 			for (i = 0; i < vsap->vsa_aclcnt; i++) {
   2043 				(void) utf8_copy(&tmp_ace4[i].who,
   2044 				    &ace4[i].who);
   2045 			}
   2046 		}
   2047 		rvsap->vsa_aclcnt = vsap->vsa_aclcnt;
   2048 		rvsap->vsa_mask |= VSA_ACE | VSA_ACECNT;
   2049 	}
   2050 	if (vsap->vsa_mask & VSA_ACECNT) {
   2051 		if (rvsap->vsa_aclentp != NULL) {
   2052 			/*
   2053 			 * If the caller requested to only cache the
   2054 			 * count, get rid of the acl whether or not the
   2055 			 * counts are equal because it may be invalid.
   2056 			 */
   2057 			if (vsap->vsa_mask == VSA_ACECNT ||
   2058 			    rvsap->vsa_aclcnt != vsap->vsa_aclcnt) {
   2059 				vs_ace4_destroy(rvsap);
   2060 				rvsap->vsa_aclentp = NULL;
   2061 				rvsap->vsa_mask &= ~VSA_ACE;
   2062 			}
   2063 		}
   2064 		rvsap->vsa_aclcnt = vsap->vsa_aclcnt;
   2065 		rvsap->vsa_mask |= VSA_ACECNT;
   2066 	}
   2067 	mutex_exit(&rp->r_statelock);
   2068 }
   2069 
   2070 /*
   2071  * This should ONLY be called on the ACL cache (rnode4_t.r_secattr).  The cache
   2072  * is stored as a nfsv4 acl meaning the vsecattr_t.vsa_aclentp is a list of
   2073  * nfsace4 entries and vsecattr_t.vsa_dfaclentp is NULL or not populated.
   2074  */
   2075 void
   2076 nfs4_acl_free_cache(vsecattr_t *vsap)
   2077 {
   2078 	if (vsap == NULL)
   2079 		return;
   2080 
   2081 	if (vsap->vsa_aclentp != NULL)
   2082 		vs_ace4_destroy(vsap);
   2083 
   2084 	kmem_free(vsap, sizeof (*vsap));
   2085 	vsap = NULL;
   2086 }
   2087 
   2088 static int
   2089 validate_idmapping(utf8string *orig_who, uid_t mapped_id, int isuser,
   2090 	int isserver, int just_count)
   2091 {
   2092 	if (u8s_mapped_to_nobody(orig_who, mapped_id, isuser)) {
   2093 		if (isserver) {
   2094 			char	*who = NULL;
   2095 			uint_t	len = 0;
   2096 
   2097 			/*
   2098 			 * This code path gets executed on the server
   2099 			 * in the case that we are setting an ACL.
   2100 			 *
   2101 			 * We silently got our who value (who@domain)
   2102 			 * mapped to "nobody" (possibly because the
   2103 			 * nfsmapid daemon was unresponsive).
   2104 			 * We NEVER want to silently map the user or
   2105 			 * group to "nobody" as this could end up
   2106 			 * wrongly giving access to user or group
   2107 			 * "nobody" rather than the entity it was
   2108 			 * meant for.
   2109 			 */
   2110 			who = utf8_to_str(orig_who, &len, NULL);
   2111 			DTRACE_PROBE1(nfs4__acl__nobody, char *, who);
   2112 			if (who != NULL)
   2113 				kmem_free(who, len);
   2114 			return (NFS4ERR_BADOWNER);
   2115 		} else {
   2116 			char	*who = NULL;
   2117 			uint_t	len = 0;
   2118 			/* CLIENT */
   2119 			/*
   2120 			 * This code path gets executed on the client
   2121 			 * when we are getting an ACL.
   2122 			 *
   2123 			 * If the caller just requested the count
   2124 			 * don't fail the request just because we
   2125 			 * failed mapping the other portions of the
   2126 			 * ACL.  Things such as vn_createat expect it's
   2127 			 * call to VOP_GETSECATTR (to get the
   2128 			 * default acl count) to succeed in order to
   2129 			 * create a file.
   2130 			 *
   2131 			 * If the caller requested more than the count,
   2132 			 * return an error as we will not want to
   2133 			 * silently map user or group to "nobody"
   2134 			 * because of the semantics that an ACL
   2135 			 * modification interface (i.e. - setfacl -m)
   2136 			 * may use to modify an ACL (i.e. - get the ACL
   2137 			 * then use it as a basis for setting the
   2138 			 * modified ACL).
   2139 			 */
   2140 			who = utf8_to_str(orig_who, &len, NULL);
   2141 			if (just_count) {
   2142 				DTRACE_PROBE1(nfs4__acl__nobody, char *, who);
   2143 				if (who != NULL)
   2144 					kmem_free(who, len);
   2145 				return (0);
   2146 			} else {
   2147 				DTRACE_PROBE1(nfs4__acl__nobody, char *, who);
   2148 				if (who != NULL)
   2149 					kmem_free(who, len);
   2150 				return (EACCES);
   2151 			}
   2152 		}
   2153 	}
   2154 	return (0);
   2155 }
   2156 /*
   2157  * Returns 1 if the who, utf8string was mapped to UID_NOBODY or GID_NOBODY.
   2158  * Returns 0 if the who, utf8string was mapped correctly.
   2159  */
   2160 static int
   2161 u8s_mapped_to_nobody(utf8string *orig_who, uid_t mapped_id, int isuser)
   2162 {
   2163 	if (orig_who->utf8string_len == 6 &&
   2164 	    bcmp("nobody", orig_who->utf8string_val, 6) == 0)
   2165 		return (0);
   2166 
   2167 	if (isuser)
   2168 		return (mapped_id == UID_NOBODY);
   2169 
   2170 	return (mapped_id == GID_NOBODY);
   2171 }
   2172