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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * The following naming convention is used in function names.
29 * If an argument is one or more aclent_t, we use "aent".
30 * If an argument is one or more nfsace4, we use "ace4".
31 * If an argument is one or more ace_t, we use "acet".
33 * If there is an aggregate of the one above...
34 * If it's contained in a vsecattr_t, we prepend "vs_".
35 * If it's contained in an "array" (pointer) and length, we prepend "ln_".
37 * Thus, for example, suppose you have a function that converts an
38 * array of aclent_t structures into an array of nfsace4 structures,
39 * it's name would be "ln_aent_to_ace4".
43 #include <nfs/nfs4_kprot.h>
45 #include <nfs/rnode4.h>
46 #include <sys/cmn_err.h>
47 #include <sys/systm.h>
50 #define ACE4_POSIX_SUPPORTED_BITS (ACE4_READ_DATA | \
54 ACE4_READ_ATTRIBUTES | \
58 static int ace4vals_compare(const void *, const void *);
59 static int nfs4_ace4_list_construct(void *, void *, int);
60 static void nfs4_ace4_list_destroy(void *, void *);
61 static void ace4_list_free(ace4_list_t
*);
62 static void ace4vals_init(ace4vals_t
*, utf8string
*);
63 static void ace4_list_init(ace4_list_t
*, int);
64 static int ln_aent_preprocess(aclent_t
*, int,
65 int *, o_mode_t
*, int *, int *, int *);
66 static void ace4_make_deny(nfsace4
*, nfsace4
*, int, int, int);
67 static acemask4
mode_to_ace4_access(o_mode_t
, int, int, int, int);
68 static int ln_aent_to_ace4(aclent_t
*, int, nfsace4
**, int *, int, int);
69 static int ace4_mask_to_mode(acemask4
, o_mode_t
*, int);
70 static int ace4_allow_to_mode(acemask4
, o_mode_t
*, int);
71 static ace4vals_t
*ace4vals_find(nfsace4
*, avl_tree_t
*, int *);
72 static int ace4_to_aent_legal(nfsace4
*, int);
73 static int ace4vals_to_aent(ace4vals_t
*, aclent_t
*, ace4_list_t
*,
74 uid_t
, gid_t
, int, int);
75 static int ace4_list_to_aent(ace4_list_t
*, aclent_t
**, int *, uid_t
, gid_t
,
77 static int ln_ace4_to_aent(nfsace4
*ace4
, int n
, uid_t
, gid_t
,
78 aclent_t
**, int *, aclent_t
**, int *, int, int);
79 static int ace4_cmp(nfsace4
*, nfsace4
*);
80 static int acet_to_ace4(ace_t
*, nfsace4
*, int);
81 static int ace4_to_acet(nfsace4
*, ace_t
*, uid_t
, gid_t
, int);
82 static int validate_idmapping(utf8string
*, uid_t
*, int, int);
83 static int u8s_mapped_to_nobody(utf8string
*, uid_t
, int);
84 static void remap_id(uid_t
*, int);
85 static void ace4_mask_to_acet_mask(acemask4
, uint32_t *);
86 static void acet_mask_to_ace4_mask(uint32_t, acemask4
*);
87 static void ace4_flags_to_acet_flags(aceflag4
, uint16_t *);
88 static void acet_flags_to_ace4_flags(uint16_t, aceflag4
*);
91 * The following two functions check and set ACE4_SYNCRONIZE, ACE4_WRITE_OWNER,
92 * ACE4_DELETE and ACE4_WRITE_ATTRIBUTES.
94 static int access_mask_check(nfsace4
*, int, int, int);
95 static acemask4
access_mask_set(int, int, int, int, int);
97 static int nfs4_acl_debug
= 0;
99 #define ACL_SYNCHRONIZE_SET_DENY 0x0000001
100 #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002
101 #define ACL_SYNCHRONIZE_ERR_DENY 0x0000004
102 #define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008
104 #define ACL_WRITE_OWNER_SET_DENY 0x0000010
105 #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020
106 #define ACL_WRITE_OWNER_ERR_DENY 0x0000040
107 #define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080
109 #define ACL_DELETE_SET_DENY 0x0000100
110 #define ACL_DELETE_SET_ALLOW 0x0000200
111 #define ACL_DELETE_ERR_DENY 0x0000400
112 #define ACL_DELETE_ERR_ALLOW 0x0000800
114 #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000
115 #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000
116 #define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000
117 #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000
119 #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000
120 #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000
121 #define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000
122 #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000
124 #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000
125 #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000
126 #define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000
127 #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000
129 #define ACL_READ_NAMED_READER_SET_DENY 0x1000000
130 #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000
131 #define ACL_READ_NAMED_READER_ERR_DENY 0x4000000
132 #define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000
135 * What we will send the server upon setting an ACL on our client
137 static int nfs4_acl_client_produce
=
138 (ACL_SYNCHRONIZE_SET_ALLOW
|
139 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
140 ACL_WRITE_ATTRS_WRITER_SET_DENY
);
143 * What we will accept upon getting an ACL on our client
145 static int nfs4_acl_client_consume
=
146 (ACL_WRITE_OWNER_ERR_DENY
|
147 ACL_WRITE_OWNER_ERR_ALLOW
|
148 ACL_WRITE_ATTRS_OWNER_ERR_DENY
|
149 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
150 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
|
151 ACL_WRITE_ATTRS_WRITER_SET_DENY
);
154 * What we will produce as an ACL on a newly created file
156 static int nfs4_acl_server_produce
=
157 (ACL_SYNCHRONIZE_SET_ALLOW
|
158 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
159 ACL_WRITE_ATTRS_WRITER_SET_DENY
);
162 * What we will accept upon setting an ACL on our server
164 static int nfs4_acl_server_consume
=
165 (ACL_SYNCHRONIZE_ERR_DENY
|
166 ACL_DELETE_ERR_DENY
|
167 ACL_WRITE_OWNER_ERR_DENY
|
168 ACL_WRITE_OWNER_ERR_ALLOW
|
169 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
170 ACL_WRITE_ATTRS_OWNER_ERR_DENY
|
171 ACL_WRITE_ATTRS_WRITER_SET_DENY
|
172 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
|
173 ACL_WRITE_NAMED_WRITER_ERR_DENY
|
174 ACL_READ_NAMED_READER_ERR_DENY
);
176 static kmem_cache_t
*nfs4_ace4vals_cache
= NULL
;
177 static kmem_cache_t
*nfs4_ace4_list_cache
= NULL
;
180 ace4vals_compare(const void *va
, const void *vb
)
182 const ace4vals_t
*a
= va
, *b
= vb
;
184 if ((a
->key
== NULL
) && (b
->key
== NULL
))
186 else if (a
->key
== NULL
)
188 else if (b
->key
== NULL
)
191 return (utf8_compare(a
->key
, b
->key
));
196 nfs4_ace4_list_construct(void *voidp
, void *arg
, int kmem_flags
)
198 ace4_list_t
*a4l
= voidp
;
200 avl_create(&a4l
->user
, ace4vals_compare
, sizeof (ace4vals_t
),
201 offsetof(ace4vals_t
, avl
));
202 avl_create(&a4l
->group
, ace4vals_compare
, sizeof (ace4vals_t
),
203 offsetof(ace4vals_t
, avl
));
209 nfs4_ace4_list_destroy(void *voidp
, void *arg
)
211 ace4_list_t
*a4l
= voidp
;
213 avl_destroy(&a4l
->user
);
214 avl_destroy(&a4l
->group
);
220 nfs4_ace4vals_cache
= kmem_cache_create("nfs4_ace4vals_cache",
221 sizeof (ace4vals_t
), 0,
226 nfs4_ace4_list_cache
= kmem_cache_create("nfs4_ace4_list_cache",
227 sizeof (ace4_list_t
), 0,
228 nfs4_ace4_list_construct
, nfs4_ace4_list_destroy
,
235 vs_acet_destroy(vsecattr_t
*vsp
)
237 if (vsp
->vsa_mask
!= (VSA_ACE
| VSA_ACECNT
))
240 if ((vsp
->vsa_aclentp
!= NULL
) &&
241 (vsp
->vsa_aclcnt
> 0) &&
242 (vsp
->vsa_mask
& VSA_ACE
) &&
243 (vsp
->vsa_mask
& VSA_ACECNT
))
244 kmem_free(vsp
->vsa_aclentp
,
245 vsp
->vsa_aclcnt
* sizeof (ace_t
));
247 vsp
->vsa_aclentp
= NULL
;
252 vs_ace4_destroy(vsecattr_t
*vsp
)
257 if (vsp
->vsa_mask
!= (VSA_ACE
| VSA_ACECNT
))
260 if ((vsp
->vsa_aclentp
!= NULL
) &&
261 (vsp
->vsa_aclcnt
> 0) &&
262 (vsp
->vsa_mask
& VSA_ACE
) &&
263 (vsp
->vsa_mask
& VSA_ACECNT
)) {
264 for (i
= 0; i
< vsp
->vsa_aclcnt
; i
++) {
265 ace4
= (nfsace4
*)vsp
->vsa_aclentp
+ i
;
266 if ((ace4
->who
.utf8string_len
> 0) &&
267 (ace4
->who
.utf8string_val
!= NULL
))
268 kmem_free(ace4
->who
.utf8string_val
,
269 ace4
->who
.utf8string_len
);
271 ace4
->who
.utf8string_val
= NULL
;
272 ace4
->who
.utf8string_len
= 0;
275 kmem_free(vsp
->vsa_aclentp
,
276 vsp
->vsa_aclcnt
* sizeof (nfsace4
));
279 vsp
->vsa_aclentp
= NULL
;
284 vs_aent_destroy(vsecattr_t
*vsp
)
286 if (vsp
->vsa_mask
& (VSA_ACE
| VSA_ACECNT
))
289 if ((vsp
->vsa_aclentp
!= NULL
) &&
290 (vsp
->vsa_aclcnt
> 0) &&
291 (vsp
->vsa_mask
& VSA_ACL
) &&
292 (vsp
->vsa_mask
& VSA_ACLCNT
))
293 kmem_free(vsp
->vsa_aclentp
,
294 vsp
->vsa_aclcnt
* sizeof (aclent_t
));
295 if ((vsp
->vsa_dfaclentp
!= NULL
) &&
296 (vsp
->vsa_dfaclcnt
> 0) &&
297 (vsp
->vsa_mask
& VSA_DFACL
) &&
298 (vsp
->vsa_mask
& VSA_DFACLCNT
))
299 kmem_free(vsp
->vsa_dfaclentp
,
300 vsp
->vsa_dfaclcnt
* sizeof (aclent_t
));
302 vsp
->vsa_aclentp
= NULL
;
305 vsp
->vsa_dfaclentp
= NULL
;
310 * free all data associated with an ace4_list
313 ace4_list_free(ace4_list_t
*a4l
)
321 /* free all nodes, but don't destroy the trees themselves */
323 while ((node
= avl_destroy_nodes(&a4l
->user
, &cookie
)) != NULL
)
324 kmem_cache_free(nfs4_ace4vals_cache
, node
);
326 while ((node
= avl_destroy_nodes(&a4l
->group
, &cookie
)) != NULL
)
327 kmem_cache_free(nfs4_ace4vals_cache
, node
);
329 /* free the container itself */
330 kmem_cache_free(nfs4_ace4_list_cache
, a4l
);
334 ace4vals_init(ace4vals_t
*vals
, utf8string
*key
)
336 bzero(vals
, sizeof (*vals
));
337 vals
->allowed
= ACE4_MASK_UNDEFINED
;
338 vals
->denied
= ACE4_MASK_UNDEFINED
;
339 vals
->mask
= ACE4_MASK_UNDEFINED
;
344 ace4_list_init(ace4_list_t
*a4l
, int dfacl_flag
)
346 ace4vals_init(&a4l
->user_obj
, NULL
);
347 ace4vals_init(&a4l
->group_obj
, NULL
);
348 ace4vals_init(&a4l
->other_obj
, NULL
);
353 a4l
->state
= ace4_unused
;
355 a4l
->dfacl_flag
= dfacl_flag
;
359 * Make an initial pass over an array of aclent_t's. Gather
360 * information such as an ACL_MASK (if any), number of users,
361 * number of groups, and whether the array needs to be sorted.
364 ln_aent_preprocess(aclent_t
*aclent
, int n
,
365 int *hasmask
, o_mode_t
*mask
,
366 int *numuser
, int *numgroup
, int *needsort
)
378 for (i
= 0; i
< n
; i
++) {
379 if (aclent
[i
].a_type
< curtype
)
381 else if (aclent
[i
].a_type
> curtype
)
382 curtype
= aclent
[i
].a_type
;
383 if (aclent
[i
].a_type
& USER
)
385 if (aclent
[i
].a_type
& (GROUP
| GROUP_OBJ
))
387 if (aclent
[i
].a_type
& CLASS_OBJ
) {
389 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
390 "ln_aent_preprocess: multiple CLASS_OBJs "
396 *mask
= aclent
[i
].a_perm
;
401 if ((! *hasmask
) && (*numuser
+ *numgroup
> 1)) {
402 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
403 "ln_aent_preprocess: no CLASS_OBJs "
414 access_mask_set(int haswriteperm
, int hasreadperm
, int isowner
, int isallow
,
417 acemask4 access_mask
= 0;
418 int nfs4_acl_produce
;
419 int synchronize_set
= 0, write_owner_set
= 0;
420 int delete_set
= 0, write_attrs_set
= 0;
421 int read_named_set
= 0, write_named_set
= 0;
424 nfs4_acl_produce
= nfs4_acl_server_produce
;
426 nfs4_acl_produce
= nfs4_acl_client_produce
;
429 synchronize_set
= ACL_SYNCHRONIZE_SET_ALLOW
;
430 write_owner_set
= ACL_WRITE_OWNER_SET_ALLOW
;
431 delete_set
= ACL_DELETE_SET_ALLOW
;
433 read_named_set
= ACL_READ_NAMED_READER_SET_ALLOW
;
435 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
437 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
438 else if (haswriteperm
)
439 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
441 synchronize_set
= ACL_SYNCHRONIZE_SET_DENY
;
442 write_owner_set
= ACL_WRITE_OWNER_SET_DENY
;
443 delete_set
= ACL_DELETE_SET_DENY
;
445 read_named_set
= ACL_READ_NAMED_READER_SET_DENY
;
447 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
449 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
450 else if (haswriteperm
)
451 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
454 * If the entity is not the owner and does not
455 * have write permissions ACE4_WRITE_ATTRIBUTES will
456 * always go in the DENY ACE.
458 access_mask
|= ACE4_WRITE_ATTRIBUTES
;
461 if (nfs4_acl_produce
& synchronize_set
)
462 access_mask
|= ACE4_SYNCHRONIZE
;
463 if (nfs4_acl_produce
& write_owner_set
)
464 access_mask
|= ACE4_WRITE_OWNER
;
465 if (nfs4_acl_produce
& delete_set
)
466 access_mask
|= ACE4_DELETE
;
467 if (nfs4_acl_produce
& write_attrs_set
)
468 access_mask
|= ACE4_WRITE_ATTRIBUTES
;
469 if (nfs4_acl_produce
& read_named_set
)
470 access_mask
|= ACE4_READ_NAMED_ATTRS
;
471 if (nfs4_acl_produce
& write_named_set
)
472 access_mask
|= ACE4_WRITE_NAMED_ATTRS
;
474 return (access_mask
);
478 * Given an nfsace4 (presumably an ALLOW entry), make a
479 * corresponding DENY entry at the address given.
482 ace4_make_deny(nfsace4
*allow
, nfsace4
*deny
, int isdir
, int isowner
,
485 bcopy(allow
, deny
, sizeof (nfsace4
));
487 (void) utf8_copy(&allow
->who
, &deny
->who
);
489 deny
->type
= ACE4_ACCESS_DENIED_ACE_TYPE
;
490 deny
->access_mask
^= ACE4_POSIX_SUPPORTED_BITS
;
492 deny
->access_mask
^= ACE4_DELETE_CHILD
;
494 deny
->access_mask
&= ~(ACE4_SYNCHRONIZE
| ACE4_WRITE_OWNER
|
495 ACE4_DELETE
| ACE4_WRITE_ATTRIBUTES
| ACE4_READ_NAMED_ATTRS
|
496 ACE4_WRITE_NAMED_ATTRS
);
497 deny
->access_mask
|= access_mask_set((allow
->access_mask
&
498 ACE4_WRITE_DATA
), (allow
->access_mask
& ACE4_READ_DATA
), isowner
,
503 * Given an o_mode_t, convert it into an access_mask as used
504 * by nfsace4, assuming aclent_t -> nfsace4 semantics.
507 mode_to_ace4_access(o_mode_t mode
, int isdir
, int isowner
, int isallow
,
511 int haswriteperm
= 0;
515 haswriteperm
= (mode
& 02);
516 hasreadperm
= (mode
& 04);
518 haswriteperm
= !(mode
& 02);
519 hasreadperm
= !(mode
& 04);
523 * The following call takes care of correctly setting the following
524 * mask bits in the access_mask:
525 * ACE4_SYNCHRONIZE, ACE4_WRITE_OWNER, ACE4_DELETE,
526 * ACE4_WRITE_ATTRIBUTES, ACE4_WRITE_NAMED_ATTRS, ACE4_READ_NAMED_ATTRS
528 access
= access_mask_set(haswriteperm
, hasreadperm
, isowner
, isallow
,
532 access
|= ACE4_READ_ACL
| ACE4_READ_ATTRIBUTES
;
534 access
|= ACE4_WRITE_ACL
;
537 access
|= ACE4_WRITE_ACL
;
542 access
|= ACE4_READ_DATA
;
546 access
|= ACE4_WRITE_DATA
|
549 access
|= ACE4_DELETE_CHILD
;
553 access
|= ACE4_EXECUTE
;
560 * Convert an array of aclent_t into an array of nfsace4 entries,
561 * following POSIX draft -> nfsv4 conversion semantics as outlined in
565 ln_aent_to_ace4(aclent_t
*aclent
, int n
, nfsace4
**acepp
, int *rescount
,
566 int isdir
, int isserver
)
570 int numuser
, numgroup
, needsort
;
572 int i
, groupi
= 0, skip
;
573 nfsace4
*acep
, *result
= NULL
;
576 error
= ln_aent_preprocess(aclent
, n
, &hasmask
, &mask
,
577 &numuser
, &numgroup
, &needsort
);
581 /* allow + deny for each aclent */
585 * stick extra deny on the group_obj and on each
586 * user|group for the mask (the group_obj was added
587 * into the count for numgroup)
589 resultsize
+= numuser
+ numgroup
;
590 /* ... and don't count the mask itself */
594 /* sort the source if necessary */
596 ksort((caddr_t
)aclent
, n
, sizeof (aclent_t
), cmp2acls
);
598 result
= acep
= kmem_zalloc(resultsize
* sizeof (nfsace4
), KM_SLEEP
);
600 for (i
= 0; i
< n
; i
++) {
602 * don't process CLASS_OBJ (mask); mask was grabbed in
603 * ln_aent_preprocess()
605 if (aclent
[i
].a_type
& CLASS_OBJ
)
608 /* If we need an ACL_MASK emulator, prepend it now */
610 (aclent
[i
].a_type
& (USER
| GROUP
| GROUP_OBJ
))) {
611 acep
->type
= ACE4_ACCESS_DENIED_ACE_TYPE
;
613 if (aclent
[i
].a_type
& GROUP_OBJ
) {
614 (void) str_to_utf8(ACE4_WHO_GROUP
, &acep
->who
);
615 acep
->flag
|= ACE4_IDENTIFIER_GROUP
;
617 } else if (aclent
[i
].a_type
& USER
) {
619 * On the client, we do not allow an ACL with
620 * ACEs containing the UID_UNKNOWN user to be
621 * set. This is because having UID_UNKNOWN in
622 * an ACE can only come from the user having
623 * done a read-modify-write ACL manipulation
624 * (e.g. setfacl -m or chmod A+) when there
625 * was an ACE with an unmappable group already
628 if (aclent
[i
].a_id
== UID_UNKNOWN
&&
631 nfs4clnt__err__acl__uid__unknown
);
632 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
633 "ln_aent_to_ace4: UID_UNKNOWN is "
634 "not allowed in the ACL"));
639 error
= nfs_idmap_uid_str(aclent
[i
].a_id
,
640 &acep
->who
, isserver
);
643 * Same rule as UID_UNKNOWN (above).
645 if (aclent
[i
].a_id
== GID_UNKNOWN
&&
648 nfs4clnt__err__acl__gid__unknown
);
649 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
650 "ln_aent_to_ace4: GID_UNKNOWN is "
651 "not allowed in the ACL"));
656 error
= nfs_idmap_gid_str(aclent
[i
].a_id
,
657 &acep
->who
, isserver
);
658 acep
->flag
|= ACE4_IDENTIFIER_GROUP
;
661 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
662 "ln_aent_to_ace4: idmap translate "
663 "failed with %d", error
));
666 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
667 acep
->flag
|= ACE4_INHERIT_ONLY_ACE
|
668 ACE4_FILE_INHERIT_ACE
|
669 ACE4_DIRECTORY_INHERIT_ACE
;
672 * Set the access mask for the prepended deny
673 * ace. To do this, we invert the mask (found
674 * in ln_aent_preprocess()) then convert it to an
675 * DENY ace access_mask.
677 acep
->access_mask
= mode_to_ace4_access((mask
^ 07),
678 isdir
, 0, 0, isserver
);
682 /* handle a_perm -> access_mask */
683 acep
->access_mask
= mode_to_ace4_access(aclent
[i
].a_perm
,
684 isdir
, aclent
[i
].a_type
& USER_OBJ
, 1, isserver
);
686 /* emulate a default aclent */
687 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
688 acep
->flag
|= ACE4_INHERIT_ONLY_ACE
|
689 ACE4_FILE_INHERIT_ACE
|
690 ACE4_DIRECTORY_INHERIT_ACE
;
694 * handle a_perm and a_id
696 * this must be done last, since it involves the
697 * corresponding deny aces, which are handled
698 * differently for each different a_type.
700 if (aclent
[i
].a_type
& USER_OBJ
) {
701 (void) str_to_utf8(ACE4_WHO_OWNER
, &acep
->who
);
702 ace4_make_deny(acep
, acep
+ 1, isdir
, TRUE
, isserver
);
704 } else if (aclent
[i
].a_type
& USER
) {
705 error
= nfs_idmap_uid_str(aclent
[i
].a_id
, &acep
->who
,
708 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
709 "ln_aent_to_ace4: uid idmap failed "
710 "with error %d", error
));
713 ace4_make_deny(acep
, acep
+ 1, isdir
, FALSE
, isserver
);
715 } else if (aclent
[i
].a_type
& (GROUP_OBJ
| GROUP
)) {
716 if (aclent
[i
].a_type
& GROUP_OBJ
) {
717 (void) str_to_utf8(ACE4_WHO_GROUP
, &acep
->who
);
720 error
= nfs_idmap_gid_str(aclent
[i
].a_id
,
721 &acep
->who
, isserver
);
724 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
725 "ln_aent_to_ace4: gid idmap failed "
726 "with error %d", error
));
729 acep
->flag
|= ACE4_IDENTIFIER_GROUP
;
731 * Set the corresponding deny for the group ace.
733 * The deny aces go after all of the groups, unlike
734 * everything else, where they immediately follow
737 * We calculate "skip", the number of slots to
738 * skip ahead for the deny ace, here.
741 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
743 * (2 * numgroup) - 1 - groupi
744 * (2 * numgroup) to account for MD + A
745 * - 1 to account for the fact that we're on the
746 * access (A), not the mask (MD)
747 * - groupi to account for the fact that we have
748 * passed up groupi number of MD's.
750 skip
= (2 * numgroup
) - 1 - groupi
;
751 ace4_make_deny(acep
, acep
+ skip
, isdir
, FALSE
,
754 * If we just did the last group, skip acep past
755 * all of the denies; else, just move ahead one.
757 if (++groupi
>= numgroup
)
758 acep
+= numgroup
+ 1;
761 } else if (aclent
[i
].a_type
& OTHER_OBJ
) {
762 (void) str_to_utf8(ACE4_WHO_EVERYONE
, &acep
->who
);
763 ace4_make_deny(acep
, acep
+ 1, isdir
, FALSE
, isserver
);
766 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
767 "ln_aent_to_ace4: aclent_t with invalid type: %x",
775 *rescount
= resultsize
;
780 if ((result
!= NULL
) && (resultsize
> 0)) {
781 /* free any embedded "who" strings */
782 for (i
= 0; i
< resultsize
; i
++) {
784 if ((acep
->who
.utf8string_len
> 0) &&
785 (acep
->who
.utf8string_val
!= NULL
)) {
786 kmem_free(acep
->who
.utf8string_val
,
787 acep
->who
.utf8string_len
);
791 /* free the nfsace4 block */
792 kmem_free(result
, resultsize
* sizeof (nfsace4
));
800 * Convert a POSIX draft ACL (in a vsecattr_t) to an NFSv4 ACL, following
801 * the semantics of the IETF draft, draft-ietf-nfsv4-acl-mapping-01.txt.
804 vs_aent_to_ace4(vsecattr_t
*aclentacl
, vsecattr_t
*vs_ace4
,
805 int isdir
, int isserver
)
808 nfsace4
*acebuf
= NULL
;
810 nfsace4
*dfacebuf
= NULL
;
813 /* initialize vs_ace4 in case we can't complete our work */
814 vs_ace4
->vsa_mask
= 0;
815 vs_ace4
->vsa_aclentp
= NULL
;
816 vs_ace4
->vsa_aclcnt
= 0;
817 vs_ace4
->vsa_dfaclentp
= NULL
;
818 vs_ace4
->vsa_dfaclcnt
= 0;
819 vs_ace4
->vsa_aclentsz
= 0;
821 if (! (aclentacl
->vsa_mask
& (VSA_ACL
| VSA_ACLCNT
|
822 VSA_DFACL
| VSA_DFACLCNT
))) {
823 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
824 "vs_aent_to_ace4: vsa_mask lacking proper mask"));
829 if ((aclentacl
->vsa_aclcnt
< 3) &&
830 (aclentacl
->vsa_mask
& (VSA_ACL
| VSA_ACLCNT
))) {
831 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
832 "vs_aent_to_ace4: too small vsa_aclcnt, %d",
833 aclentacl
->vsa_aclcnt
));
838 if ((aclentacl
->vsa_dfaclcnt
!= 0) && (aclentacl
->vsa_dfaclcnt
< 3) &&
839 (aclentacl
->vsa_mask
& (VSA_DFACL
| VSA_DFACLCNT
))) {
840 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
841 "vs_aent_to_ace4: too small vsa_dfaclcnt, %d",
842 aclentacl
->vsa_dfaclcnt
));
847 if (aclentacl
->vsa_aclcnt
> 0) {
848 error
= ln_aent_to_ace4(aclentacl
->vsa_aclentp
,
849 aclentacl
->vsa_aclcnt
, &acebuf
, &acecnt
, isdir
, isserver
);
853 if (aclentacl
->vsa_dfaclcnt
> 0) {
854 error
= ln_aent_to_ace4(aclentacl
->vsa_dfaclentp
,
855 aclentacl
->vsa_dfaclcnt
, &dfacebuf
, &dfacecnt
, isdir
,
861 vs_ace4
->vsa_aclcnt
= acecnt
+ dfacecnt
;
862 /* on error, this is freed by vs_ace4_destroy() */
863 if (vs_ace4
->vsa_aclcnt
> 0)
864 vs_ace4
->vsa_aclentp
= kmem_zalloc(vs_ace4
->vsa_aclcnt
*
865 sizeof (nfsace4
), KM_SLEEP
);
867 * When we bcopy the nfsace4's, the result (in vsa_aclentp)
868 * will have its "who.utf8string_val" pointer pointing to the
869 * allocated strings. Thus, when we free acebuf and dbacebuf,
870 * we don't need to free these strings.
873 bcopy(acebuf
, vs_ace4
->vsa_aclentp
, acecnt
* sizeof (nfsace4
));
875 bcopy(dfacebuf
, (nfsace4
*) vs_ace4
->vsa_aclentp
+ acecnt
,
876 dfacecnt
* sizeof (nfsace4
));
877 vs_ace4
->vsa_mask
= VSA_ACE
| VSA_ACECNT
;
881 vs_ace4_destroy(vs_ace4
);
884 kmem_free(acebuf
, acecnt
* sizeof (nfsace4
));
885 if (dfacebuf
!= NULL
)
886 kmem_free(dfacebuf
, dfacecnt
* sizeof (nfsace4
));
892 ace4_mask_to_mode(acemask4 mask
, o_mode_t
*modep
, int isdir
)
896 acemask4 bits
, wantbits
;
899 if (mask
& ACE4_READ_DATA
)
903 wantbits
= (ACE4_WRITE_DATA
|
906 wantbits
|= ACE4_DELETE_CHILD
;
907 bits
= mask
& wantbits
;
909 if (bits
!= wantbits
) {
910 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
911 "ace4_mask_to_mode: bad subset of write flags "
920 if (mask
& ACE4_EXECUTE
) {
931 ace4_allow_to_mode(acemask4 mask
, o_mode_t
*modep
, int isdir
)
933 /* ACE4_READ_ACL and ACE4_READ_ATTRIBUTES must both be set */
934 if ((mask
& (ACE4_READ_ACL
| ACE4_READ_ATTRIBUTES
)) !=
935 (ACE4_READ_ACL
| ACE4_READ_ATTRIBUTES
)) {
939 return (ace4_mask_to_mode(mask
, modep
, isdir
));
943 * Find or create an ace4vals holder for a given id and avl tree.
945 * Note that only one thread will ever touch these avl trees, so
946 * there is no need for locking.
949 ace4vals_find(nfsace4
*ace4
, avl_tree_t
*avl
, int *num
)
954 key
.key
= &ace4
->who
;
955 rc
= avl_find(avl
, &key
, &where
);
959 /* this memory is freed by ln_ace4_to_aent()->ace4_list_free() */
960 rc
= kmem_cache_alloc(nfs4_ace4vals_cache
, KM_SLEEP
);
961 ace4vals_init(rc
, &ace4
->who
);
962 avl_insert(avl
, rc
, where
);
969 access_mask_check(nfsace4
*ace4p
, int mask_bit
, int isserver
, int isowner
)
971 int set_deny
, err_deny
;
972 int set_allow
, err_allow
;
973 int nfs4_acl_consume
;
974 int haswriteperm
, hasreadperm
;
976 if (ace4p
->type
== ACE4_ACCESS_DENIED_ACE_TYPE
) {
977 haswriteperm
= (ace4p
->access_mask
& ACE4_WRITE_DATA
) ? 0 : 1;
978 hasreadperm
= (ace4p
->access_mask
& ACE4_READ_DATA
) ? 0 : 1;
980 haswriteperm
= (ace4p
->access_mask
& ACE4_WRITE_DATA
) ? 1 : 0;
981 hasreadperm
= (ace4p
->access_mask
& ACE4_READ_DATA
) ? 1 : 0;
985 nfs4_acl_consume
= nfs4_acl_server_consume
;
987 nfs4_acl_consume
= nfs4_acl_client_consume
;
989 if (mask_bit
== ACE4_SYNCHRONIZE
) {
990 set_deny
= ACL_SYNCHRONIZE_SET_DENY
;
991 err_deny
= ACL_SYNCHRONIZE_ERR_DENY
;
992 set_allow
= ACL_SYNCHRONIZE_SET_ALLOW
;
993 err_allow
= ACL_SYNCHRONIZE_ERR_ALLOW
;
994 } else if (mask_bit
== ACE4_WRITE_OWNER
) {
995 set_deny
= ACL_WRITE_OWNER_SET_DENY
;
996 err_deny
= ACL_WRITE_OWNER_ERR_DENY
;
997 set_allow
= ACL_WRITE_OWNER_SET_ALLOW
;
998 err_allow
= ACL_WRITE_OWNER_ERR_ALLOW
;
999 } else if (mask_bit
== ACE4_DELETE
) {
1000 set_deny
= ACL_DELETE_SET_DENY
;
1001 err_deny
= ACL_DELETE_ERR_DENY
;
1002 set_allow
= ACL_DELETE_SET_ALLOW
;
1003 err_allow
= ACL_DELETE_ERR_ALLOW
;
1004 } else if (mask_bit
== ACE4_WRITE_ATTRIBUTES
) {
1006 set_deny
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
1007 err_deny
= ACL_WRITE_ATTRS_OWNER_ERR_DENY
;
1008 set_allow
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
1009 err_allow
= ACL_WRITE_ATTRS_OWNER_ERR_ALLOW
;
1010 } else if (haswriteperm
) {
1011 set_deny
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
1012 err_deny
= ACL_WRITE_ATTRS_WRITER_ERR_DENY
;
1013 set_allow
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
1014 err_allow
= ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
;
1016 if ((ace4p
->access_mask
& mask_bit
) &&
1017 (ace4p
->type
& ACE4_ACCESS_ALLOWED_ACE_TYPE
)) {
1022 } else if (mask_bit
== ACE4_READ_NAMED_ATTRS
) {
1026 set_deny
= ACL_READ_NAMED_READER_SET_DENY
;
1027 err_deny
= ACL_READ_NAMED_READER_ERR_DENY
;
1028 set_allow
= ACL_READ_NAMED_READER_SET_ALLOW
;
1029 err_allow
= ACL_READ_NAMED_READER_ERR_ALLOW
;
1030 } else if (mask_bit
== ACE4_WRITE_NAMED_ATTRS
) {
1034 set_deny
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
1035 err_deny
= ACL_WRITE_NAMED_WRITER_ERR_DENY
;
1036 set_allow
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
1037 err_allow
= ACL_WRITE_NAMED_WRITER_ERR_ALLOW
;
1041 if (ace4p
->type
== ACE4_ACCESS_DENIED_ACE_TYPE
) {
1042 if (nfs4_acl_consume
& set_deny
) {
1043 if (!(ace4p
->access_mask
& mask_bit
)) {
1046 } else if (nfs4_acl_consume
& err_deny
) {
1047 if (ace4p
->access_mask
& mask_bit
) {
1052 /* ACE4_ACCESS_ALLOWED_ACE_TYPE */
1053 if (nfs4_acl_consume
& set_allow
) {
1054 if (!(ace4p
->access_mask
& mask_bit
)) {
1057 } else if (nfs4_acl_consume
& err_allow
) {
1058 if (ace4p
->access_mask
& mask_bit
) {
1067 ace4_to_aent_legal(nfsace4
*ace4p
, int isserver
)
1072 /* check for NULL who string */
1073 if (ace4p
->who
.utf8string_val
== NULL
) {
1074 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1075 "ace4_to_aent_legal: NULL who string"));
1080 /* only ALLOW or DENY */
1081 if ((ace4p
->type
!= ACE4_ACCESS_ALLOWED_ACE_TYPE
) &&
1082 (ace4p
->type
!= ACE4_ACCESS_DENIED_ACE_TYPE
)) {
1083 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1084 "ace4_to_aent_legal: neither allow nor deny"));
1089 /* check for invalid flags */
1090 if (ace4p
->flag
& ~(ACE4_VALID_FLAG_BITS
)) {
1091 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1092 "ace4_to_aent_legal: invalid flags: %x", ace4p
->flag
));
1097 /* some flags are illegal */
1098 if (ace4p
->flag
& (ACE4_SUCCESSFUL_ACCESS_ACE_FLAG
|
1099 ACE4_FAILED_ACCESS_ACE_FLAG
|
1100 ACE4_NO_PROPAGATE_INHERIT_ACE
)) {
1101 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1102 "ace4_to_aent_legal: illegal flags: %x", ace4p
->flag
));
1107 /* check for invalid masks */
1108 if (ace4p
->access_mask
& ~(ACE4_VALID_MASK_BITS
)) {
1109 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1110 "ace4_to_aent_legal: invalid mask: %x",
1111 ace4p
->access_mask
));
1116 if ((ace4p
->who
.utf8string_len
== 6) &&
1117 (bcmp(ACE4_WHO_OWNER
, ace4p
->who
.utf8string_val
, 6) == 0)) {
1123 error
= access_mask_check(ace4p
, ACE4_SYNCHRONIZE
, isserver
, isowner
);
1127 error
= access_mask_check(ace4p
, ACE4_WRITE_OWNER
, isserver
, isowner
);
1131 error
= access_mask_check(ace4p
, ACE4_DELETE
, isserver
, isowner
);
1135 error
= access_mask_check(ace4p
, ACE4_WRITE_ATTRIBUTES
, isserver
,
1140 error
= access_mask_check(ace4p
, ACE4_READ_NAMED_ATTRS
, isserver
,
1145 error
= access_mask_check(ace4p
, ACE4_WRITE_NAMED_ATTRS
, isserver
,
1150 /* more detailed checking of masks */
1151 if (ace4p
->type
== ACE4_ACCESS_ALLOWED_ACE_TYPE
) {
1152 if (! (ace4p
->access_mask
& ACE4_READ_ATTRIBUTES
)) {
1156 if ((ace4p
->access_mask
& ACE4_WRITE_DATA
) &&
1157 (! (ace4p
->access_mask
& ACE4_APPEND_DATA
))) {
1161 if ((! (ace4p
->access_mask
& ACE4_WRITE_DATA
)) &&
1162 (ace4p
->access_mask
& ACE4_APPEND_DATA
)) {
1168 /* ACL enforcement */
1169 if ((ace4p
->access_mask
& ACE4_READ_ACL
) &&
1170 (ace4p
->type
!= ACE4_ACCESS_ALLOWED_ACE_TYPE
)) {
1174 if (ace4p
->access_mask
& ACE4_WRITE_ACL
) {
1175 if ((ace4p
->type
== ACE4_ACCESS_DENIED_ACE_TYPE
) &&
1180 if ((ace4p
->type
== ACE4_ACCESS_ALLOWED_ACE_TYPE
) &&
1192 ace4vals_to_aent(ace4vals_t
*vals
, aclent_t
*dest
, ace4_list_t
*list
,
1193 uid_t owner
, gid_t group
, int isdir
, int isserver
)
1196 acemask4 flips
= ACE4_POSIX_SUPPORTED_BITS
;
1199 flips
|= ACE4_DELETE_CHILD
;
1200 if (vals
->allowed
!= (vals
->denied
^ flips
)) {
1201 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1202 "ace4vals_to_aent: mis-matched allow/deny pair: %x/%x",
1203 vals
->allowed
, vals
->denied
));
1207 if ((list
->hasmask
) && (list
->acl_mask
!= vals
->mask
) &&
1208 (vals
->aent_type
& (USER
| GROUP
| GROUP_OBJ
))) {
1209 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1210 "ace4vals_to_aent: entry is missing mask"));
1214 error
= ace4_allow_to_mode(vals
->allowed
, &dest
->a_perm
, isdir
);
1217 dest
->a_type
= vals
->aent_type
;
1218 if (dest
->a_type
& (USER
| GROUP
)) {
1219 if (dest
->a_type
& USER
)
1220 error
= nfs_idmap_str_uid(vals
->key
, &dest
->a_id
,
1223 error
= nfs_idmap_str_gid(vals
->key
, &dest
->a_id
,
1226 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1227 "ace4vals_to_aent: idmap failed with %d", error
));
1228 if (isserver
&& (error
== EPERM
))
1229 error
= NFS4ERR_BADOWNER
;
1233 error
= validate_idmapping(vals
->key
, &dest
->a_id
,
1234 (dest
->a_type
& USER
? 1 : 0), isserver
);
1238 } else if (dest
->a_type
& USER_OBJ
) {
1240 } else if (dest
->a_type
& GROUP_OBJ
) {
1242 } else if (dest
->a_type
& OTHER_OBJ
) {
1245 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1246 "ace4vals_to_aent: dest->a_type invalid: %x "
1247 "(internal error)", dest
->a_type
));
1257 ace4_list_to_aent(ace4_list_t
*list
, aclent_t
**aclentp
, int *aclcnt
,
1258 uid_t owner
, gid_t group
, int isdir
, int isserver
)
1261 aclent_t
*aent
, *result
= NULL
;
1265 if ((list
->seen
& (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) !=
1266 (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) {
1267 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1268 "ace4_list_to_aent: required aclent_t entites missing"));
1272 if ((! list
->hasmask
) && (list
->numusers
+ list
->numgroups
> 0)) {
1273 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1274 "ace4_list_to_aent: CLASS_OBJ (mask) missing"));
1279 resultcount
= 3 + list
->numusers
+ list
->numgroups
;
1281 * This must be the same condition as below, when we add the CLASS_OBJ
1284 if ((list
->hasmask
) || (! list
->dfacl_flag
))
1287 result
= aent
= kmem_alloc(resultcount
* sizeof (aclent_t
), KM_SLEEP
);
1290 ASSERT(list
->user_obj
.aent_type
& USER_OBJ
);
1291 error
= ace4vals_to_aent(&list
->user_obj
, aent
, list
, owner
, group
,
1299 for (vals
= avl_first(&list
->user
); vals
!= NULL
;
1300 vals
= AVL_NEXT(&list
->user
, vals
)) {
1301 ASSERT(vals
->aent_type
& USER
);
1302 error
= ace4vals_to_aent(vals
, aent
, list
, owner
, group
,
1309 ASSERT(list
->group_obj
.aent_type
& GROUP_OBJ
);
1310 error
= ace4vals_to_aent(&list
->group_obj
, aent
, list
, owner
, group
,
1317 for (vals
= avl_first(&list
->group
); vals
!= NULL
;
1318 vals
= AVL_NEXT(&list
->group
, vals
)) {
1319 ASSERT(vals
->aent_type
& GROUP
);
1320 error
= ace4vals_to_aent(vals
, aent
, list
, owner
, group
,
1327 * CLASS_OBJ (aka ACL_MASK)
1329 * An ACL_MASK is not fabricated if the ACL is a default ACL.
1330 * This is to follow UFS's behavior.
1332 if ((list
->hasmask
) || (! list
->dfacl_flag
)) {
1333 if (list
->hasmask
) {
1334 acemask4 flips
= ACE4_POSIX_SUPPORTED_BITS
;
1336 flips
|= ACE4_DELETE_CHILD
;
1337 error
= ace4_mask_to_mode(list
->acl_mask
^ flips
,
1338 &aent
->a_perm
, isdir
);
1342 /* fabricate the ACL_MASK from the group permissions */
1343 error
= ace4_mask_to_mode(list
->group_obj
.allowed
,
1344 &aent
->a_perm
, isdir
);
1349 aent
->a_type
= CLASS_OBJ
| list
->dfacl_flag
;
1353 ASSERT(list
->other_obj
.aent_type
& OTHER_OBJ
);
1354 error
= ace4vals_to_aent(&list
->other_obj
, aent
, list
, owner
, group
,
1361 *aclcnt
= resultcount
;
1366 kmem_free(result
, resultcount
* sizeof (aclent_t
));
1373 * Convert a list of nfsace4 entries to equivalent regular and default
1374 * aclent_t lists. Return error (ENOTSUP) when conversion is not possible.
1377 ln_ace4_to_aent(nfsace4
*ace4
, int n
,
1378 uid_t owner
, gid_t group
,
1379 aclent_t
**aclentp
, int *aclcnt
,
1380 aclent_t
**dfaclentp
, int *dfaclcnt
,
1381 int isdir
, int isserver
)
1387 ace4_list_t
*normacl
= NULL
, *dfacl
= NULL
, *acl
;
1395 /* we need at least user_obj, group_obj, and other_obj */
1397 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1398 "ln_ace4_to_aent: too few nfsace4 entries: %d", n
));
1403 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1404 "ln_ace4_to_aent: NULL source"));
1409 normacl
= kmem_cache_alloc(nfs4_ace4_list_cache
, KM_SLEEP
);
1410 ace4_list_init(normacl
, 0);
1411 dfacl
= kmem_cache_alloc(nfs4_ace4_list_cache
, KM_SLEEP
);
1412 ace4_list_init(dfacl
, ACL_DEFAULT
);
1414 /* process every nfsace4... */
1415 for (i
= 0; i
< n
; i
++) {
1418 /* rule out certain cases quickly */
1419 error
= ace4_to_aent_legal(ace4p
, isserver
);
1424 * Turn off these bits in order to not have to worry about
1425 * them when doing the checks for compliments.
1427 ace4p
->access_mask
&= ~(ACE4_WRITE_OWNER
| ACE4_DELETE
|
1428 ACE4_SYNCHRONIZE
| ACE4_WRITE_ATTRIBUTES
|
1429 ACE4_READ_NAMED_ATTRS
| ACE4_WRITE_NAMED_ATTRS
);
1431 /* see if this should be a regular or default acl */
1432 bits
= ace4p
->flag
&
1433 (ACE4_INHERIT_ONLY_ACE
|
1434 ACE4_FILE_INHERIT_ACE
|
1435 ACE4_DIRECTORY_INHERIT_ACE
);
1437 /* all or nothing on these inherit bits */
1438 if (bits
!= (ACE4_INHERIT_ONLY_ACE
|
1439 ACE4_FILE_INHERIT_ACE
|
1440 ACE4_DIRECTORY_INHERIT_ACE
)) {
1441 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1442 "ln_ace4_to_aent: bad inherit flags "
1452 if ((ace4p
->who
.utf8string_len
== 6) &&
1453 (bcmp(ACE4_WHO_OWNER
,
1454 ace4p
->who
.utf8string_val
, 6) == 0)) {
1455 if (acl
->state
> ace4_user_obj
) {
1456 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1457 "ln_ace4_to_aent: OWNER@ found "
1462 acl
->state
= ace4_user_obj
;
1463 acl
->seen
|= USER_OBJ
;
1464 vals
= &acl
->user_obj
;
1465 vals
->aent_type
= USER_OBJ
| acl
->dfacl_flag
;
1466 } else if ((ace4p
->who
.utf8string_len
== 9) &&
1467 (bcmp(ACE4_WHO_EVERYONE
, ace4p
->who
.utf8string_val
, 9)
1469 acl
->state
= ace4_other_obj
;
1470 acl
->seen
|= OTHER_OBJ
;
1471 vals
= &acl
->other_obj
;
1472 vals
->aent_type
= OTHER_OBJ
| acl
->dfacl_flag
;
1473 } else if ((ace4p
->who
.utf8string_len
== 6) &&
1474 (bcmp(ACE4_WHO_GROUP
, ace4p
->who
.utf8string_val
, 6) == 0)) {
1475 if (acl
->state
> ace4_group
) {
1476 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1477 "ln_ace4_to_aent: group entry found "
1482 acl
->seen
|= GROUP_OBJ
;
1483 vals
= &acl
->group_obj
;
1484 vals
->aent_type
= GROUP_OBJ
| acl
->dfacl_flag
;
1485 acl
->state
= ace4_group
;
1486 } else if (ace4p
->flag
& ACE4_IDENTIFIER_GROUP
) {
1487 if (acl
->state
> ace4_group
) {
1488 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1489 "ln_ace4_to_aent: group entry found "
1495 vals
= ace4vals_find(ace4p
, &acl
->group
,
1497 vals
->aent_type
= GROUP
| acl
->dfacl_flag
;
1498 acl
->state
= ace4_group
;
1500 if (acl
->state
> ace4_user
) {
1501 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1502 "ln_ace4_to_aent: user entry found "
1507 acl
->state
= ace4_user
;
1509 vals
= ace4vals_find(ace4p
, &acl
->user
,
1511 vals
->aent_type
= USER
| acl
->dfacl_flag
;
1513 ASSERT(acl
->state
> ace4_unused
);
1515 if (ace4p
->type
== ACE4_ACCESS_ALLOWED_ACE_TYPE
) {
1516 /* no more than one allowed per aclent_t */
1517 if (vals
->allowed
!= ACE4_MASK_UNDEFINED
) {
1518 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1519 "ln_ace4_to_aent: too many ALLOWs "
1524 vals
->allowed
= ace4p
->access_mask
;
1527 * it's a DENY; if there was a previous DENY, it
1528 * must have been an ACL_MASK.
1530 if (vals
->denied
!= ACE4_MASK_UNDEFINED
) {
1531 /* ACL_MASK is for USER and GROUP only */
1532 if ((acl
->state
!= ace4_user
) &&
1533 (acl
->state
!= ace4_group
)) {
1534 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1535 "ln_ace4_to_aent: ACL_MASK-like "
1536 "DENY found on non-user/non-group "
1542 if (! acl
->hasmask
) {
1544 acl
->acl_mask
= vals
->denied
;
1545 /* check for mismatched ACL_MASK emulations */
1546 } else if (acl
->acl_mask
!= vals
->denied
) {
1547 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1548 "ln_ace4_to_aent: ACL_MASK "
1553 vals
->mask
= vals
->denied
;
1555 vals
->denied
= ace4p
->access_mask
;
1559 /* done collating; produce the aclent_t lists */
1560 if (normacl
->state
!= ace4_unused
) {
1561 error
= ace4_list_to_aent(normacl
, aclentp
, aclcnt
,
1562 owner
, group
, isdir
, isserver
);
1566 if (dfacl
->state
!= ace4_unused
) {
1567 error
= ace4_list_to_aent(dfacl
, dfaclentp
, dfaclcnt
,
1568 owner
, group
, isdir
, isserver
);
1574 if (normacl
!= NULL
)
1575 ace4_list_free(normacl
);
1577 ace4_list_free(dfacl
);
1583 * Convert an NFSv4 ACL (in a vsecattr_t) to a POSIX draft ACL, following
1584 * the semantics of NFSv4_to_POSIX.html. Contact fsh-group@sun.com to
1585 * obtain this document.
1588 vs_ace4_to_aent(vsecattr_t
*vs_ace4
, vsecattr_t
*vs_aent
,
1589 uid_t owner
, gid_t group
, int isdir
, int isserver
)
1593 error
= ln_ace4_to_aent(vs_ace4
->vsa_aclentp
, vs_ace4
->vsa_aclcnt
,
1595 (aclent_t
**)&vs_aent
->vsa_aclentp
, &vs_aent
->vsa_aclcnt
,
1596 (aclent_t
**)&vs_aent
->vsa_dfaclentp
, &vs_aent
->vsa_dfaclcnt
,
1601 vs_aent
->vsa_mask
= VSA_ACL
| VSA_ACLCNT
| VSA_DFACL
| VSA_DFACLCNT
;
1602 if ((vs_aent
->vsa_aclcnt
== 0) && (vs_aent
->vsa_dfaclcnt
== 0)) {
1603 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1604 "vs_ace4_to_aent: neither ACL nor default ACL found"));
1611 if (vs_aent
!= NULL
)
1612 vs_aent_destroy(vs_aent
);
1619 * compare two ace4 acls
1623 ace4_cmp(nfsace4
*a
, nfsace4
*b
)
1625 if (a
->type
< b
->type
)
1627 if (a
->type
> b
->type
)
1629 if (a
->flag
< b
->flag
)
1631 if (a
->flag
> b
->flag
)
1633 if (a
->access_mask
< b
->access_mask
)
1635 if (a
->access_mask
> b
->access_mask
)
1637 return (utf8_compare(&a
->who
, &b
->who
));
1641 ln_ace4_cmp(nfsace4
*a
, nfsace4
* b
, int n
)
1646 for (i
= 0; i
< n
; i
++) {
1647 rc
= ace4_cmp(a
+ i
, b
+ i
);
1655 * Convert an ace_t to an nfsace4; the primary difference being
1656 * strings versus integer uid/gids.
1659 acet_to_ace4(ace_t
*ace
, nfsace4
*nfsace4
, int isserver
)
1664 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1665 "acet_to_ace4: NULL source"));
1669 if (nfsace4
== NULL
) {
1670 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1671 "acet_to_ace4: NULL destination"));
1676 switch (ace
->a_type
) {
1677 case ACE_ACCESS_ALLOWED_ACE_TYPE
:
1678 nfsace4
->type
= ACE4_ACCESS_ALLOWED_ACE_TYPE
;
1680 case ACE_ACCESS_DENIED_ACE_TYPE
:
1681 nfsace4
->type
= ACE4_ACCESS_DENIED_ACE_TYPE
;
1684 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1685 "acet_to_ace4: unsupported type: %x", ace
->a_type
));
1692 acet_mask_to_ace4_mask(ace
->a_access_mask
, &nfsace4
->access_mask
);
1693 acet_flags_to_ace4_flags(ace
->a_flags
, &nfsace4
->flag
);
1695 if (ace
->a_flags
& ACE_GROUP
) {
1696 nfsace4
->flag
|= ACE4_IDENTIFIER_GROUP
;
1697 (void) str_to_utf8(ACE4_WHO_GROUP
, &nfsace4
->who
);
1698 } else if (ace
->a_flags
& ACE_IDENTIFIER_GROUP
) {
1699 nfsace4
->flag
|= ACE4_IDENTIFIER_GROUP
;
1701 * On the client, we do not allow an ACL with ACEs containing
1702 * the "unknown"/GID_UNKNOWN group to be set. This is because
1703 * it having GID_UNKNOWN in an ACE can only come from
1704 * the user having done a read-modify-write ACL manipulation
1705 * (e.g. setfacl -m or chmod A+) when there was an ACE with
1706 * an unmappable group already present.
1708 if (ace
->a_who
== GID_UNKNOWN
&& !isserver
) {
1709 DTRACE_PROBE(nfs4clnt__err__acl__gid__unknown
);
1710 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1711 "acet_to_ace4: GID_UNKNOWN is not allowed in "
1716 error
= nfs_idmap_gid_str(ace
->a_who
, &nfsace4
->who
, isserver
);
1718 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1719 "acet_to_ace4: idmap failed with %d", error
));
1720 } else if (ace
->a_flags
& ACE_OWNER
) {
1721 (void) str_to_utf8(ACE4_WHO_OWNER
, &nfsace4
->who
);
1722 } else if (ace
->a_flags
& ACE_EVERYONE
) {
1723 (void) str_to_utf8(ACE4_WHO_EVERYONE
, &nfsace4
->who
);
1726 * Same rule as GID_UNKNOWN (above).
1728 if (ace
->a_who
== UID_UNKNOWN
&& !isserver
) {
1729 DTRACE_PROBE(nfs4clnt__err__acl__uid__unknown
);
1730 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1731 "acet_to_ace4: UID_UNKNOWN is not allowed in "
1736 error
= nfs_idmap_uid_str(ace
->a_who
, &nfsace4
->who
, isserver
);
1738 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1739 "acet_to_ace4: idmap failed with %d", error
));
1747 * Convert an nfsace4 to an ace_t, the primary difference being
1748 * integer uid/gids versus strings.
1751 ace4_to_acet(nfsace4
*nfsace4
, ace_t
*ace
, uid_t owner
, gid_t group
,
1756 if (nfsace4
== NULL
) {
1757 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1758 "ace4_to_acet: NULL source"));
1762 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1763 "ace4_to_acet: NULL destination"));
1767 switch (nfsace4
->type
) {
1768 case ACE4_ACCESS_ALLOWED_ACE_TYPE
:
1769 ace
->a_type
= ACE_ACCESS_ALLOWED_ACE_TYPE
;
1771 case ACE4_ACCESS_DENIED_ACE_TYPE
:
1772 ace
->a_type
= ACE_ACCESS_DENIED_ACE_TYPE
;
1775 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1776 "ace4_to_acet: unsupported type: %x", nfsace4
->type
));
1783 if (nfsace4
->flag
& ~(ACE4_VALID_FLAG_BITS
)) {
1784 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1785 "ace4_to_acet: invalid flags: %x", nfsace4
->flag
));
1790 /* check for invalid masks */
1791 if (nfsace4
->access_mask
& ~(ACE4_VALID_MASK_BITS
)) {
1792 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1793 "ace4_to_acet: invalid mask: %x", nfsace4
->access_mask
));
1798 ace4_mask_to_acet_mask(nfsace4
->access_mask
, &ace
->a_access_mask
);
1800 if (nfsace4
->flag
& ~ACE_NFSV4_SUP_FLAGS
) {
1801 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1802 "ace4_to_acet: unsupported flags: %x", nfsace4
->flag
));
1806 ace4_flags_to_acet_flags(nfsace4
->flag
, &ace
->a_flags
);
1808 if ((nfsace4
->who
.utf8string_len
== 6) &&
1809 (bcmp(ACE4_WHO_GROUP
,
1810 nfsace4
->who
.utf8string_val
, 6)) == 0) {
1812 ace
->a_flags
|= ACE_GROUP
| ACE_IDENTIFIER_GROUP
;
1813 } else if ((nfsace4
->who
.utf8string_len
== 6) &&
1814 (bcmp(ACE4_WHO_OWNER
,
1815 nfsace4
->who
.utf8string_val
, 6) == 0)) {
1816 ace
->a_flags
|= ACE_OWNER
;
1818 } else if ((nfsace4
->who
.utf8string_len
== 9) &&
1819 (bcmp(ACE4_WHO_EVERYONE
,
1820 nfsace4
->who
.utf8string_val
, 9) == 0)) {
1821 ace
->a_flags
|= ACE_EVERYONE
;
1823 } else if (nfsace4
->flag
& ACE4_IDENTIFIER_GROUP
) {
1824 ace
->a_flags
|= ACE_IDENTIFIER_GROUP
;
1825 error
= nfs_idmap_str_gid(&nfsace4
->who
,
1826 &ace
->a_who
, isserver
);
1828 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1829 "ace4_to_acet: idmap failed with %d",
1831 if (isserver
&& (error
== EPERM
))
1832 error
= NFS4ERR_BADOWNER
;
1835 error
= validate_idmapping(&nfsace4
->who
,
1836 &ace
->a_who
, FALSE
, isserver
);
1840 error
= nfs_idmap_str_uid(&nfsace4
->who
,
1841 &ace
->a_who
, isserver
);
1843 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
1844 "ace4_to_acet: idmap failed with %d",
1846 if (isserver
&& (error
== EPERM
))
1847 error
= NFS4ERR_BADOWNER
;
1850 error
= validate_idmapping(&nfsace4
->who
,
1851 &ace
->a_who
, TRUE
, isserver
);
1861 ace4_mask_to_acet_mask(acemask4 ace4_mask
, uint32_t *acet_mask
)
1865 if (ace4_mask
& ACE4_READ_DATA
)
1866 *acet_mask
|= ACE_READ_DATA
;
1867 if (ace4_mask
& ACE4_WRITE_DATA
)
1868 *acet_mask
|= ACE_WRITE_DATA
;
1869 if (ace4_mask
& ACE4_APPEND_DATA
)
1870 *acet_mask
|= ACE_APPEND_DATA
;
1871 if (ace4_mask
& ACE4_READ_NAMED_ATTRS
)
1872 *acet_mask
|= ACE_READ_NAMED_ATTRS
;
1873 if (ace4_mask
& ACE4_WRITE_NAMED_ATTRS
)
1874 *acet_mask
|= ACE_WRITE_NAMED_ATTRS
;
1875 if (ace4_mask
& ACE4_EXECUTE
)
1876 *acet_mask
|= ACE_EXECUTE
;
1877 if (ace4_mask
& ACE4_DELETE_CHILD
)
1878 *acet_mask
|= ACE_DELETE_CHILD
;
1879 if (ace4_mask
& ACE4_READ_ATTRIBUTES
)
1880 *acet_mask
|= ACE_READ_ATTRIBUTES
;
1881 if (ace4_mask
& ACE4_WRITE_ATTRIBUTES
)
1882 *acet_mask
|= ACE_WRITE_ATTRIBUTES
;
1883 if (ace4_mask
& ACE4_DELETE
)
1884 *acet_mask
|= ACE_DELETE
;
1885 if (ace4_mask
& ACE4_READ_ACL
)
1886 *acet_mask
|= ACE_READ_ACL
;
1887 if (ace4_mask
& ACE4_WRITE_ACL
)
1888 *acet_mask
|= ACE_WRITE_ACL
;
1889 if (ace4_mask
& ACE4_WRITE_OWNER
)
1890 *acet_mask
|= ACE_WRITE_OWNER
;
1891 if (ace4_mask
& ACE4_SYNCHRONIZE
)
1892 *acet_mask
|= ACE_SYNCHRONIZE
;
1896 acet_mask_to_ace4_mask(uint32_t acet_mask
, acemask4
*ace4_mask
)
1900 if (acet_mask
& ACE_READ_DATA
)
1901 *ace4_mask
|= ACE4_READ_DATA
;
1902 if (acet_mask
& ACE_WRITE_DATA
)
1903 *ace4_mask
|= ACE4_WRITE_DATA
;
1904 if (acet_mask
& ACE_APPEND_DATA
)
1905 *ace4_mask
|= ACE_APPEND_DATA
;
1906 if (acet_mask
& ACE4_READ_NAMED_ATTRS
)
1907 *ace4_mask
|= ACE_READ_NAMED_ATTRS
;
1908 if (acet_mask
& ACE_WRITE_NAMED_ATTRS
)
1909 *ace4_mask
|= ACE4_WRITE_NAMED_ATTRS
;
1910 if (acet_mask
& ACE_EXECUTE
)
1911 *ace4_mask
|= ACE4_EXECUTE
;
1912 if (acet_mask
& ACE_DELETE_CHILD
)
1913 *ace4_mask
|= ACE4_DELETE_CHILD
;
1914 if (acet_mask
& ACE_READ_ATTRIBUTES
)
1915 *ace4_mask
|= ACE4_READ_ATTRIBUTES
;
1916 if (acet_mask
& ACE_WRITE_ATTRIBUTES
)
1917 *ace4_mask
|= ACE4_WRITE_ATTRIBUTES
;
1918 if (acet_mask
& ACE_DELETE
)
1919 *ace4_mask
|= ACE4_DELETE
;
1920 if (acet_mask
& ACE_READ_ACL
)
1921 *ace4_mask
|= ACE4_READ_ACL
;
1922 if (acet_mask
& ACE_WRITE_ACL
)
1923 *ace4_mask
|= ACE4_WRITE_ACL
;
1924 if (acet_mask
& ACE_WRITE_OWNER
)
1925 *ace4_mask
|= ACE4_WRITE_OWNER
;
1926 if (acet_mask
& ACE_SYNCHRONIZE
)
1927 *ace4_mask
|= ACE4_SYNCHRONIZE
;
1931 ace4_flags_to_acet_flags(aceflag4 ace4_flags
, uint16_t *acet_flags
)
1935 if (ace4_flags
& ACE4_FILE_INHERIT_ACE
)
1936 *acet_flags
|= ACE_FILE_INHERIT_ACE
;
1937 if (ace4_flags
& ACE4_DIRECTORY_INHERIT_ACE
)
1938 *acet_flags
|= ACE_DIRECTORY_INHERIT_ACE
;
1939 if (ace4_flags
& ACE4_NO_PROPAGATE_INHERIT_ACE
)
1940 *acet_flags
|= ACE_NO_PROPAGATE_INHERIT_ACE
;
1941 if (ace4_flags
& ACE4_INHERIT_ONLY_ACE
)
1942 *acet_flags
|= ACE_INHERIT_ONLY_ACE
;
1943 if (ace4_flags
& ACE4_SUCCESSFUL_ACCESS_ACE_FLAG
)
1944 *acet_flags
|= ACE_SUCCESSFUL_ACCESS_ACE_FLAG
;
1945 if (ace4_flags
& ACE4_FAILED_ACCESS_ACE_FLAG
)
1946 *acet_flags
|= ACE_FAILED_ACCESS_ACE_FLAG
;
1947 /* ACE_IDENTIFIER_GROUP is handled in ace4_to_acet() */
1951 acet_flags_to_ace4_flags(uint16_t acet_flags
, aceflag4
*ace4_flags
)
1955 if (acet_flags
& ACE_FILE_INHERIT_ACE
)
1956 *ace4_flags
|= ACE4_FILE_INHERIT_ACE
;
1957 if (acet_flags
& ACE_DIRECTORY_INHERIT_ACE
)
1958 *ace4_flags
|= ACE4_DIRECTORY_INHERIT_ACE
;
1959 if (acet_flags
& ACE_NO_PROPAGATE_INHERIT_ACE
)
1960 *ace4_flags
|= ACE4_NO_PROPAGATE_INHERIT_ACE
;
1961 if (acet_flags
& ACE_INHERIT_ONLY_ACE
)
1962 *ace4_flags
|= ACE4_INHERIT_ONLY_ACE
;
1963 if (acet_flags
& ACE_SUCCESSFUL_ACCESS_ACE_FLAG
)
1964 *ace4_flags
|= ACE4_SUCCESSFUL_ACCESS_ACE_FLAG
;
1965 if (acet_flags
& ACE_FAILED_ACCESS_ACE_FLAG
)
1966 *ace4_flags
|= ACE4_FAILED_ACCESS_ACE_FLAG
;
1967 /* ACE4_IDENTIFIER_GROUP is handled in acet_to_ace4() */
1971 vs_ace4_to_acet(vsecattr_t
*vs_ace4
, vsecattr_t
*vs_acet
,
1972 uid_t owner
, gid_t group
, int isserver
)
1977 if ((vs_ace4
->vsa_mask
& (VSA_ACE
| VSA_ACECNT
)) !=
1978 (VSA_ACE
| VSA_ACECNT
))
1980 if (vs_ace4
->vsa_aclcnt
< 0)
1982 if ((vs_ace4
->vsa_aclcnt
== 0) || (vs_ace4
->vsa_aclentp
== NULL
))
1985 if (vs_ace4
->vsa_aclcnt
> 0) {
1986 vs_acet
->vsa_aclentp
= kmem_alloc(vs_ace4
->vsa_aclcnt
*
1987 sizeof (ace_t
), KM_SLEEP
);
1988 vs_acet
->vsa_aclentsz
= vs_ace4
->vsa_aclcnt
* sizeof (ace_t
);
1990 vs_acet
->vsa_aclentp
= NULL
;
1991 vs_acet
->vsa_aclcnt
= vs_ace4
->vsa_aclcnt
;
1992 vs_acet
->vsa_mask
= VSA_ACE
| VSA_ACECNT
;
1994 for (i
= 0; i
< vs_ace4
->vsa_aclcnt
; i
++) {
1995 error
= ace4_to_acet((nfsace4
*)(vs_ace4
->vsa_aclentp
) + i
,
1996 (ace_t
*)(vs_acet
->vsa_aclentp
) + i
, owner
, group
,
2004 vs_acet_destroy(vs_acet
);
2010 vs_acet_to_ace4(vsecattr_t
*vs_acet
, vsecattr_t
*vs_ace4
,
2016 if (! (vs_acet
->vsa_mask
& VSA_ACE
)) {
2017 NFS4_DEBUG(nfs4_acl_debug
, (CE_NOTE
,
2018 "vs_acet_to_ace4: VSA_ACE missing from mask"));
2022 if (vs_acet
->vsa_aclcnt
> 0)
2023 vs_ace4
->vsa_aclentp
= kmem_zalloc(vs_acet
->vsa_aclcnt
*
2024 sizeof (nfsace4
), KM_SLEEP
);
2026 vs_ace4
->vsa_aclentp
= NULL
;
2027 vs_ace4
->vsa_aclcnt
= vs_acet
->vsa_aclcnt
;
2028 vs_ace4
->vsa_mask
= VSA_ACE
| VSA_ACECNT
;
2030 for (i
= 0; i
< vs_acet
->vsa_aclcnt
; i
++) {
2031 error
= acet_to_ace4((ace_t
*)(vs_acet
->vsa_aclentp
) + i
,
2032 (nfsace4
*)(vs_ace4
->vsa_aclentp
) + i
, isserver
);
2039 vs_ace4_destroy(vs_ace4
);
2045 nfs4_acl_fill_cache(rnode4_t
*rp
, vsecattr_t
*vsap
)
2049 nfsace4
*tmp_ace4
, *ace4
;
2052 mutex_enter(&rp
->r_statelock
);
2053 if (rp
->r_secattr
!= NULL
)
2054 rvsap
= rp
->r_secattr
;
2056 rvsap
= kmem_zalloc(sizeof (*rvsap
), KM_NOSLEEP
);
2057 if (rvsap
== NULL
) {
2058 mutex_exit(&rp
->r_statelock
);
2061 rp
->r_secattr
= rvsap
;
2064 if (vsap
->vsa_mask
& VSA_ACE
) {
2065 if (rvsap
->vsa_aclentp
!= NULL
) {
2066 if (rvsap
->vsa_aclcnt
!= vsap
->vsa_aclcnt
) {
2067 vs_ace4_destroy(rvsap
);
2068 rvsap
->vsa_aclentp
= NULL
;
2071 * The counts are equal so we don't have to
2072 * destroy the acl entries because we'd only
2073 * have to re-allocate them, but we do have to
2074 * destroy all of the who utf8strings.
2075 * The acl that we are now filling the cache
2076 * with may have the same amount of entries as
2077 * what is currently cached, but those entries
2078 * may not be the same.
2080 ace4
= (nfsace4
*) rvsap
->vsa_aclentp
;
2081 for (i
= 0; i
< rvsap
->vsa_aclcnt
; i
++) {
2082 if (ace4
[i
].who
.utf8string_val
!= NULL
)
2084 ace4
[i
].who
.utf8string_val
,
2085 ace4
[i
].who
.utf8string_len
);
2089 if (vsap
->vsa_aclcnt
> 0) {
2090 aclsize
= vsap
->vsa_aclcnt
* sizeof (nfsace4
);
2092 if (rvsap
->vsa_aclentp
== NULL
) {
2093 rvsap
->vsa_aclentp
= kmem_alloc(aclsize
,
2097 bcopy(vsap
->vsa_aclentp
, rvsap
->vsa_aclentp
, aclsize
);
2099 tmp_ace4
= (nfsace4
*) vsap
->vsa_aclentp
;
2100 ace4
= (nfsace4
*) rvsap
->vsa_aclentp
;
2101 for (i
= 0; i
< vsap
->vsa_aclcnt
; i
++) {
2102 (void) utf8_copy(&tmp_ace4
[i
].who
,
2106 rvsap
->vsa_aclcnt
= vsap
->vsa_aclcnt
;
2107 rvsap
->vsa_mask
|= VSA_ACE
| VSA_ACECNT
;
2109 if (vsap
->vsa_mask
& VSA_ACECNT
) {
2110 if (rvsap
->vsa_aclentp
!= NULL
) {
2112 * If the caller requested to only cache the
2113 * count, get rid of the acl whether or not the
2114 * counts are equal because it may be invalid.
2116 if (vsap
->vsa_mask
== VSA_ACECNT
||
2117 rvsap
->vsa_aclcnt
!= vsap
->vsa_aclcnt
) {
2118 vs_ace4_destroy(rvsap
);
2119 rvsap
->vsa_aclentp
= NULL
;
2120 rvsap
->vsa_mask
&= ~VSA_ACE
;
2123 rvsap
->vsa_aclcnt
= vsap
->vsa_aclcnt
;
2124 rvsap
->vsa_mask
|= VSA_ACECNT
;
2126 mutex_exit(&rp
->r_statelock
);
2130 * This should ONLY be called on the ACL cache (rnode4_t.r_secattr). The cache
2131 * is stored as a nfsv4 acl meaning the vsecattr_t.vsa_aclentp is a list of
2132 * nfsace4 entries and vsecattr_t.vsa_dfaclentp is NULL or not populated.
2135 nfs4_acl_free_cache(vsecattr_t
*vsap
)
2140 if (vsap
->vsa_aclentp
!= NULL
)
2141 vs_ace4_destroy(vsap
);
2143 kmem_free(vsap
, sizeof (*vsap
));
2148 validate_idmapping(utf8string
*orig_who
, uid_t
*mapped_id
, int isuser
,
2151 if (u8s_mapped_to_nobody(orig_who
, *mapped_id
, isuser
)) {
2157 * This code path gets executed on the server
2158 * in the case that we are setting an ACL.
2160 * We silently got our who value (who@domain)
2161 * mapped to "nobody" (possibly because the
2162 * nfsmapid daemon was unresponsive).
2163 * We NEVER want to silently map the user or
2164 * group to "nobody" as this could end up
2165 * wrongly giving access to user or group
2166 * "nobody" rather than the entity it was
2169 who
= utf8_to_str(orig_who
, &len
, NULL
);
2170 DTRACE_PROBE1(nfs4__acl__nobody
, char *, who
);
2172 kmem_free(who
, len
);
2173 return (NFS4ERR_BADOWNER
);
2179 * This code path gets executed on the client
2180 * when we are getting an ACL.
2182 * We do not want to silently map user or group to
2183 * "nobody" because of the semantics that an ACL
2184 * modification interface (i.e. - setfacl -m, chmod A+)
2185 * may use to modify an ACL (i.e. - get the ACL
2186 * then use it as a basis for setting the
2187 * modified ACL). Therefore, change the mapping.
2189 who
= utf8_to_str(orig_who
, &len
, NULL
);
2190 DTRACE_PROBE1(nfs4__acl__nobody
, char *, who
);
2192 kmem_free(who
, len
);
2195 * Re-mapped from UID_NOBODY/GID_NOBODY
2196 * to UID_UNKNOWN/GID_UNKNOWN and return.
2198 remap_id(mapped_id
, isuser
);
2205 * Returns 1 if the who, utf8string was mapped to UID_NOBODY or GID_NOBODY.
2206 * Returns 0 if the who, utf8string was mapped correctly.
2209 u8s_mapped_to_nobody(utf8string
*orig_who
, uid_t mapped_id
, int isuser
)
2211 if (orig_who
->utf8string_len
== 6 &&
2212 bcmp("nobody", orig_who
->utf8string_val
, 6) == 0)
2216 return (mapped_id
== UID_NOBODY
);
2218 return (mapped_id
== GID_NOBODY
);
2222 * This function is used in the case that the utf8string passed over the wire
2223 * was mapped to UID_NOBODY or GID_NOBODY and we will remap the id to
2224 * to the appropriate mapping. That is UID_UNKNOWN or GID_UNKNOWN.
2227 remap_id(uid_t
*id
, int isuser
)