1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2008-2010 Edward Tomasz Napiera��a <trasz@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/*
29 * ACL support routines specific to NFSv4 access control lists.  These are
30 * utility routines for code common across file systems implementing NFSv4
31 * ACLs.
32 */
33
34#ifdef _KERNEL
35
36#include <sys/param.h>
37#include <sys/kernel.h>
38#include <sys/module.h>
39#include <sys/systm.h>
40#include <sys/mount.h>
41#include <sys/priv.h>
42#include <sys/vnode.h>
43#include <sys/errno.h>
44#include <sys/stat.h>
45#include <sys/sysctl.h>
46#include <sys/acl.h>
47#else
48#include <errno.h>
49#include <assert.h>
50#include <sys/acl.h>
51#include <sys/stat.h>
52#define KASSERT(a, b) assert(a)
53#define CTASSERT(a)
54
55#endif /* !_KERNEL */
56
57#ifdef _KERNEL
58
59static void	acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode);
60
61static int	acl_nfs4_old_semantics = 0;
62
63SYSCTL_INT(_vfs, OID_AUTO, acl_nfs4_old_semantics, CTLFLAG_RW,
64    &acl_nfs4_old_semantics, 0, "Use pre-PSARC/2010/029 NFSv4 ACL semantics");
65
66static struct {
67	accmode_t accmode;
68	int mask;
69} accmode2mask[] = {{VREAD, ACL_READ_DATA},
70		    {VWRITE, ACL_WRITE_DATA},
71		    {VAPPEND, ACL_APPEND_DATA},
72		    {VEXEC, ACL_EXECUTE},
73		    {VREAD_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
74		    {VWRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
75		    {VDELETE_CHILD, ACL_DELETE_CHILD},
76		    {VREAD_ATTRIBUTES, ACL_READ_ATTRIBUTES},
77		    {VWRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
78		    {VDELETE, ACL_DELETE},
79		    {VREAD_ACL, ACL_READ_ACL},
80		    {VWRITE_ACL, ACL_WRITE_ACL},
81		    {VWRITE_OWNER, ACL_WRITE_OWNER},
82		    {VSYNCHRONIZE, ACL_SYNCHRONIZE},
83		    {0, 0}};
84
85static int
86_access_mask_from_accmode(accmode_t accmode)
87{
88	int access_mask = 0, i;
89
90	for (i = 0; accmode2mask[i].accmode != 0; i++) {
91		if (accmode & accmode2mask[i].accmode)
92			access_mask |= accmode2mask[i].mask;
93	}
94
95	/*
96	 * VAPPEND is just a modifier for VWRITE; if the caller asked
97	 * for 'VAPPEND | VWRITE', we want to check for ACL_APPEND_DATA only.
98	 */
99	if (access_mask & ACL_APPEND_DATA)
100		access_mask &= ~ACL_WRITE_DATA;
101
102	return (access_mask);
103}
104
105/*
106 * Return 0, iff access is allowed, 1 otherwise.
107 */
108static int
109_acl_denies(const struct acl *aclp, int access_mask, struct ucred *cred,
110    int file_uid, int file_gid, int *denied_explicitly)
111{
112	int i;
113	const struct acl_entry *entry;
114
115	if (denied_explicitly != NULL)
116		*denied_explicitly = 0;
117
118	KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES,
119	    ("aclp->acl_cnt <= ACL_MAX_ENTRIES"));
120
121	for (i = 0; i < aclp->acl_cnt; i++) {
122		entry = &(aclp->acl_entry[i]);
123
124		if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
125		    entry->ae_entry_type != ACL_ENTRY_TYPE_DENY)
126			continue;
127		if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY)
128			continue;
129		switch (entry->ae_tag) {
130		case ACL_USER_OBJ:
131			if (file_uid != cred->cr_uid)
132				continue;
133			break;
134		case ACL_USER:
135			if (entry->ae_id != cred->cr_uid)
136				continue;
137			break;
138		case ACL_GROUP_OBJ:
139			if (!groupmember(file_gid, cred))
140				continue;
141			break;
142		case ACL_GROUP:
143			if (!groupmember(entry->ae_id, cred))
144				continue;
145			break;
146		default:
147			KASSERT(entry->ae_tag == ACL_EVERYONE,
148			    ("entry->ae_tag == ACL_EVERYONE"));
149		}
150
151		if (entry->ae_entry_type == ACL_ENTRY_TYPE_DENY) {
152			if (entry->ae_perm & access_mask) {
153				if (denied_explicitly != NULL)
154					*denied_explicitly = 1;
155				return (1);
156			}
157		}
158
159		access_mask &= ~(entry->ae_perm);
160		if (access_mask == 0)
161			return (0);
162	}
163
164	if (access_mask == 0)
165		return (0);
166
167	return (1);
168}
169
170int
171vaccess_acl_nfs4(__enum_uint8(vtype) type, uid_t file_uid, gid_t file_gid,
172    struct acl *aclp, accmode_t accmode, struct ucred *cred)
173{
174	accmode_t priv_granted = 0;
175	int denied, explicitly_denied, access_mask, is_directory,
176	    must_be_owner = 0;
177	mode_t file_mode = 0;
178
179	KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND |
180	    VEXPLICIT_DENY | VREAD_NAMED_ATTRS | VWRITE_NAMED_ATTRS |
181	    VDELETE_CHILD | VREAD_ATTRIBUTES | VWRITE_ATTRIBUTES | VDELETE |
182	    VREAD_ACL | VWRITE_ACL | VWRITE_OWNER | VSYNCHRONIZE)) == 0,
183	    ("invalid bit in accmode"));
184	KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE),
185	    	("VAPPEND without VWRITE"));
186
187	if (accmode & VADMIN)
188		must_be_owner = 1;
189
190	/*
191	 * Ignore VSYNCHRONIZE permission.
192	 */
193	accmode &= ~VSYNCHRONIZE;
194
195	access_mask = _access_mask_from_accmode(accmode);
196
197	if (type == VDIR)
198		is_directory = 1;
199	else
200		is_directory = 0;
201
202	/*
203	 * File owner is always allowed to read and write the ACL
204	 * and basic attributes.  This is to prevent a situation
205	 * where user would change ACL in a way that prevents him
206	 * from undoing the change.
207	 */
208	if (file_uid == cred->cr_uid)
209		access_mask &= ~(ACL_READ_ACL | ACL_WRITE_ACL |
210		    ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES);
211
212	/*
213	 * Ignore append permission for regular files; use write
214	 * permission instead.
215	 */
216	if (!is_directory && (access_mask & ACL_APPEND_DATA)) {
217		access_mask &= ~ACL_APPEND_DATA;
218		access_mask |= ACL_WRITE_DATA;
219	}
220
221	denied = _acl_denies(aclp, access_mask, cred, file_uid, file_gid,
222	    &explicitly_denied);
223
224	if (must_be_owner) {
225		if (file_uid != cred->cr_uid)
226			denied = EPERM;
227	}
228
229	/*
230	 * For VEXEC, ensure that at least one execute bit is set for
231	 * non-directories. We have to check the mode here to stay
232	 * consistent with execve(2). See the test in
233	 * exec_check_permissions().
234	 */
235	acl_nfs4_sync_mode_from_acl(&file_mode, aclp);
236	if (!denied && !is_directory && (accmode & VEXEC) &&
237	    (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
238		denied = EACCES;
239
240	if (!denied)
241		return (0);
242
243	/*
244	 * Access failed.  Iff it was not denied explicitly and
245	 * VEXPLICIT_DENY flag was specified, allow access.
246	 */
247	if ((accmode & VEXPLICIT_DENY) && explicitly_denied == 0)
248		return (0);
249
250	accmode &= ~VEXPLICIT_DENY;
251
252	/*
253	 * No match.  Try to use privileges, if there are any.
254	 */
255	if (is_directory) {
256		if ((accmode & VEXEC) && !priv_check_cred(cred, PRIV_VFS_LOOKUP))
257			priv_granted |= VEXEC;
258	} else {
259		/*
260		 * Ensure that at least one execute bit is on. Otherwise,
261		 * a privileged user will always succeed, and we don't want
262		 * this to happen unless the file really is executable.
263		 */
264		if ((accmode & VEXEC) && (file_mode &
265		    (S_IXUSR | S_IXGRP | S_IXOTH)) != 0 &&
266		    !priv_check_cred(cred, PRIV_VFS_EXEC))
267			priv_granted |= VEXEC;
268	}
269
270	if ((accmode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ))
271		priv_granted |= VREAD;
272
273	if ((accmode & (VWRITE | VAPPEND | VDELETE_CHILD)) &&
274	    !priv_check_cred(cred, PRIV_VFS_WRITE))
275		priv_granted |= (VWRITE | VAPPEND | VDELETE_CHILD);
276
277	if ((accmode & VADMIN_PERMS) &&
278	    !priv_check_cred(cred, PRIV_VFS_ADMIN))
279		priv_granted |= VADMIN_PERMS;
280
281	if ((accmode & VSTAT_PERMS) &&
282	    !priv_check_cred(cred, PRIV_VFS_STAT))
283		priv_granted |= VSTAT_PERMS;
284
285	if ((accmode & priv_granted) == accmode) {
286		return (0);
287	}
288
289	if (accmode & (VADMIN_PERMS | VDELETE_CHILD | VDELETE))
290		denied = EPERM;
291	else
292		denied = EACCES;
293
294	return (denied);
295}
296#endif /* _KERNEL */
297
298static int
299_acl_entry_matches(struct acl_entry *entry, acl_tag_t tag, acl_perm_t perm,
300    acl_entry_type_t entry_type)
301{
302	if (entry->ae_tag != tag)
303		return (0);
304
305	if (entry->ae_id != ACL_UNDEFINED_ID)
306		return (0);
307
308	if (entry->ae_perm != perm)
309		return (0);
310
311	if (entry->ae_entry_type != entry_type)
312		return (0);
313
314	if (entry->ae_flags != 0)
315		return (0);
316
317	return (1);
318}
319
320static struct acl_entry *
321_acl_append(struct acl *aclp, acl_tag_t tag, acl_perm_t perm,
322    acl_entry_type_t entry_type)
323{
324	struct acl_entry *entry;
325
326	KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES,
327	    ("aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES"));
328
329	entry = &(aclp->acl_entry[aclp->acl_cnt]);
330	aclp->acl_cnt++;
331
332	entry->ae_tag = tag;
333	entry->ae_id = ACL_UNDEFINED_ID;
334	entry->ae_perm = perm;
335	entry->ae_entry_type = entry_type;
336	entry->ae_flags = 0;
337
338	return (entry);
339}
340
341static struct acl_entry *
342_acl_duplicate_entry(struct acl *aclp, unsigned entry_index)
343{
344	unsigned i;
345
346	KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES,
347	    ("aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES"));
348
349	for (i = aclp->acl_cnt; i > entry_index; i--)
350		aclp->acl_entry[i] = aclp->acl_entry[i - 1];
351
352	aclp->acl_cnt++;
353
354	return (&(aclp->acl_entry[entry_index + 1]));
355}
356
357static void
358acl_nfs4_sync_acl_from_mode_draft(struct acl *aclp, mode_t mode,
359    int file_owner_id)
360{
361	int meets, must_append;
362	unsigned i;
363	struct acl_entry *entry, *copy, *previous,
364	    *a1, *a2, *a3, *a4, *a5, *a6;
365	mode_t amode;
366	const int READ = 04;
367	const int WRITE = 02;
368	const int EXEC = 01;
369
370	KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES,
371	    ("aclp->acl_cnt <= ACL_MAX_ENTRIES"));
372
373	/*
374	 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt
375	 *
376	 * 3.16.6.3. Applying a Mode to an Existing ACL
377	 */
378
379	/*
380	 * 1. For each ACE:
381	 */
382	for (i = 0; i < aclp->acl_cnt; i++) {
383		entry = &(aclp->acl_entry[i]);
384
385		/*
386		 * 1.1. If the type is neither ALLOW or DENY - skip.
387		 */
388		if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
389		    entry->ae_entry_type != ACL_ENTRY_TYPE_DENY)
390			continue;
391
392		/*
393		 * 1.2. If ACL_ENTRY_INHERIT_ONLY is set - skip.
394		 */
395		if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY)
396			continue;
397
398		/*
399		 * 1.3. If ACL_ENTRY_FILE_INHERIT or ACL_ENTRY_DIRECTORY_INHERIT
400		 *      are set:
401		 */
402		if (entry->ae_flags &
403		    (ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT)) {
404			/*
405			 * 1.3.1. A copy of the current ACE is made, and placed
406			 *        in the ACL immediately following the current
407			 *        ACE.
408			 */
409			copy = _acl_duplicate_entry(aclp, i);
410
411			/*
412			 * 1.3.2. In the first ACE, the flag
413			 *        ACL_ENTRY_INHERIT_ONLY is set.
414			 */
415			entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
416
417			/*
418			 * 1.3.3. In the second ACE, the following flags
419			 *        are cleared:
420			 *        ACL_ENTRY_FILE_INHERIT,
421			 *        ACL_ENTRY_DIRECTORY_INHERIT,
422			 *        ACL_ENTRY_NO_PROPAGATE_INHERIT.
423			 */
424			copy->ae_flags &= ~(ACL_ENTRY_FILE_INHERIT |
425			    ACL_ENTRY_DIRECTORY_INHERIT |
426			    ACL_ENTRY_NO_PROPAGATE_INHERIT);
427
428			/*
429			 * The algorithm continues on with the second ACE.
430			 */
431			i++;
432			entry = copy;
433		}
434
435		/*
436		 * 1.4. If it's owner@, group@ or everyone@ entry, clear
437		 *      ACL_READ_DATA, ACL_WRITE_DATA, ACL_APPEND_DATA
438		 *      and ACL_EXECUTE.  Continue to the next entry.
439		 */
440		if (entry->ae_tag == ACL_USER_OBJ ||
441		    entry->ae_tag == ACL_GROUP_OBJ ||
442		    entry->ae_tag == ACL_EVERYONE) {
443			entry->ae_perm &= ~(ACL_READ_DATA | ACL_WRITE_DATA |
444			    ACL_APPEND_DATA | ACL_EXECUTE);
445			continue;
446		}
447
448		/*
449		 * 1.5. Otherwise, if the "who" field did not match one
450		 *      of OWNER@, GROUP@, EVERYONE@:
451		 *
452		 * 1.5.1. If the type is ALLOW, check the preceding ACE.
453		 *        If it does not meet all of the following criteria:
454		 */
455		if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW)
456			continue;
457
458		meets = 0;
459		if (i > 0) {
460			meets = 1;
461			previous = &(aclp->acl_entry[i - 1]);
462
463			/*
464			 * 1.5.1.1. The type field is DENY,
465			 */
466			if (previous->ae_entry_type != ACL_ENTRY_TYPE_DENY)
467				meets = 0;
468
469			/*
470			 * 1.5.1.2. The "who" field is the same as the current
471			 *          ACE,
472			 *
473			 * 1.5.1.3. The flag bit ACE4_IDENTIFIER_GROUP
474			 *          is the same as it is in the current ACE,
475			 *          and no other flag bits are set,
476			 */
477			if (previous->ae_id != entry->ae_id ||
478			    previous->ae_tag != entry->ae_tag)
479				meets = 0;
480
481			if (previous->ae_flags)
482				meets = 0;
483
484			/*
485			 * 1.5.1.4. The mask bits are a subset of the mask bits
486			 *          of the current ACE, and are also subset of
487			 *          the following: ACL_READ_DATA,
488			 *          ACL_WRITE_DATA, ACL_APPEND_DATA, ACL_EXECUTE
489			 */
490			if (previous->ae_perm & ~(entry->ae_perm))
491				meets = 0;
492
493			if (previous->ae_perm & ~(ACL_READ_DATA |
494			    ACL_WRITE_DATA | ACL_APPEND_DATA | ACL_EXECUTE))
495				meets = 0;
496		}
497
498		if (!meets) {
499			/*
500		 	 * Then the ACE of type DENY, with a who equal
501			 * to the current ACE, flag bits equal to
502			 * (<current ACE flags> & <ACE_IDENTIFIER_GROUP>)
503			 * and no mask bits, is prepended.
504			 */
505			previous = entry;
506			entry = _acl_duplicate_entry(aclp, i);
507
508			/* Adjust counter, as we've just added an entry. */
509			i++;
510
511			previous->ae_tag = entry->ae_tag;
512			previous->ae_id = entry->ae_id;
513			previous->ae_flags = entry->ae_flags;
514			previous->ae_perm = 0;
515			previous->ae_entry_type = ACL_ENTRY_TYPE_DENY;
516		}
517
518		/*
519		 * 1.5.2. The following modifications are made to the prepended
520		 *        ACE.  The intent is to mask the following ACE
521		 *        to disallow ACL_READ_DATA, ACL_WRITE_DATA,
522		 *        ACL_APPEND_DATA, or ACL_EXECUTE, based upon the group
523		 *        permissions of the new mode.  As a special case,
524		 *        if the ACE matches the current owner of the file,
525		 *        the owner bits are used, rather than the group bits.
526		 *        This is reflected in the algorithm below.
527		 */
528		amode = mode >> 3;
529
530		/*
531		 * If ACE4_IDENTIFIER_GROUP is not set, and the "who" field
532		 * in ACE matches the owner of the file, we shift amode three
533		 * more bits, in order to have the owner permission bits
534		 * placed in the three low order bits of amode.
535		 */
536		if (entry->ae_tag == ACL_USER && entry->ae_id == file_owner_id)
537			amode = amode >> 3;
538
539		if (entry->ae_perm & ACL_READ_DATA) {
540			if (amode & READ)
541				previous->ae_perm &= ~ACL_READ_DATA;
542			else
543				previous->ae_perm |= ACL_READ_DATA;
544		}
545
546		if (entry->ae_perm & ACL_WRITE_DATA) {
547			if (amode & WRITE)
548				previous->ae_perm &= ~ACL_WRITE_DATA;
549			else
550				previous->ae_perm |= ACL_WRITE_DATA;
551		}
552
553		if (entry->ae_perm & ACL_APPEND_DATA) {
554			if (amode & WRITE)
555				previous->ae_perm &= ~ACL_APPEND_DATA;
556			else
557				previous->ae_perm |= ACL_APPEND_DATA;
558		}
559
560		if (entry->ae_perm & ACL_EXECUTE) {
561			if (amode & EXEC)
562				previous->ae_perm &= ~ACL_EXECUTE;
563			else
564				previous->ae_perm |= ACL_EXECUTE;
565		}
566
567		/*
568		 * 1.5.3. If ACE4_IDENTIFIER_GROUP is set in the flags
569		 *        of the ALLOW ace:
570		 *
571		 * XXX: This point is not there in the Falkner's draft.
572		 */
573		if (entry->ae_tag == ACL_GROUP &&
574		    entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) {
575			mode_t extramode, ownermode;
576			extramode = (mode >> 3) & 07;
577			ownermode = mode >> 6;
578			extramode &= ~ownermode;
579
580			if (extramode) {
581				if (extramode & READ) {
582					entry->ae_perm &= ~ACL_READ_DATA;
583					previous->ae_perm &= ~ACL_READ_DATA;
584				}
585
586				if (extramode & WRITE) {
587					entry->ae_perm &=
588					    ~(ACL_WRITE_DATA | ACL_APPEND_DATA);
589					previous->ae_perm &=
590					    ~(ACL_WRITE_DATA | ACL_APPEND_DATA);
591				}
592
593				if (extramode & EXEC) {
594					entry->ae_perm &= ~ACL_EXECUTE;
595					previous->ae_perm &= ~ACL_EXECUTE;
596				}
597			}
598		}
599	}
600
601	/*
602	 * 2. If there at least six ACEs, the final six ACEs are examined.
603	 *    If they are not equal to what we want, append six ACEs.
604	 */
605	must_append = 0;
606	if (aclp->acl_cnt < 6) {
607		must_append = 1;
608	} else {
609		a6 = &(aclp->acl_entry[aclp->acl_cnt - 1]);
610		a5 = &(aclp->acl_entry[aclp->acl_cnt - 2]);
611		a4 = &(aclp->acl_entry[aclp->acl_cnt - 3]);
612		a3 = &(aclp->acl_entry[aclp->acl_cnt - 4]);
613		a2 = &(aclp->acl_entry[aclp->acl_cnt - 5]);
614		a1 = &(aclp->acl_entry[aclp->acl_cnt - 6]);
615
616		if (!_acl_entry_matches(a1, ACL_USER_OBJ, 0,
617		    ACL_ENTRY_TYPE_DENY))
618			must_append = 1;
619		if (!_acl_entry_matches(a2, ACL_USER_OBJ, ACL_WRITE_ACL |
620		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
621		    ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_ALLOW))
622			must_append = 1;
623		if (!_acl_entry_matches(a3, ACL_GROUP_OBJ, 0,
624		    ACL_ENTRY_TYPE_DENY))
625			must_append = 1;
626		if (!_acl_entry_matches(a4, ACL_GROUP_OBJ, 0,
627		    ACL_ENTRY_TYPE_ALLOW))
628			must_append = 1;
629		if (!_acl_entry_matches(a5, ACL_EVERYONE, ACL_WRITE_ACL |
630		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
631		    ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_DENY))
632			must_append = 1;
633		if (!_acl_entry_matches(a6, ACL_EVERYONE, ACL_READ_ACL |
634		    ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS |
635		    ACL_SYNCHRONIZE, ACL_ENTRY_TYPE_ALLOW))
636			must_append = 1;
637	}
638
639	if (must_append) {
640		KASSERT(aclp->acl_cnt + 6 <= ACL_MAX_ENTRIES,
641		    ("aclp->acl_cnt <= ACL_MAX_ENTRIES"));
642
643		a1 = _acl_append(aclp, ACL_USER_OBJ, 0, ACL_ENTRY_TYPE_DENY);
644		a2 = _acl_append(aclp, ACL_USER_OBJ, ACL_WRITE_ACL |
645		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
646		    ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_ALLOW);
647		a3 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_ENTRY_TYPE_DENY);
648		a4 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_ENTRY_TYPE_ALLOW);
649		a5 = _acl_append(aclp, ACL_EVERYONE, ACL_WRITE_ACL |
650		    ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
651		    ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_DENY);
652		a6 = _acl_append(aclp, ACL_EVERYONE, ACL_READ_ACL |
653		    ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS |
654		    ACL_SYNCHRONIZE, ACL_ENTRY_TYPE_ALLOW);
655
656		KASSERT(a1 != NULL && a2 != NULL && a3 != NULL && a4 != NULL &&
657		    a5 != NULL && a6 != NULL, ("couldn't append to ACL."));
658	}
659
660	/*
661	 * 3. The final six ACEs are adjusted according to the incoming mode.
662	 */
663	if (mode & S_IRUSR)
664		a2->ae_perm |= ACL_READ_DATA;
665	else
666		a1->ae_perm |= ACL_READ_DATA;
667	if (mode & S_IWUSR)
668		a2->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
669	else
670		a1->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
671	if (mode & S_IXUSR)
672		a2->ae_perm |= ACL_EXECUTE;
673	else
674		a1->ae_perm |= ACL_EXECUTE;
675
676	if (mode & S_IRGRP)
677		a4->ae_perm |= ACL_READ_DATA;
678	else
679		a3->ae_perm |= ACL_READ_DATA;
680	if (mode & S_IWGRP)
681		a4->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
682	else
683		a3->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
684	if (mode & S_IXGRP)
685		a4->ae_perm |= ACL_EXECUTE;
686	else
687		a3->ae_perm |= ACL_EXECUTE;
688
689	if (mode & S_IROTH)
690		a6->ae_perm |= ACL_READ_DATA;
691	else
692		a5->ae_perm |= ACL_READ_DATA;
693	if (mode & S_IWOTH)
694		a6->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
695	else
696		a5->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
697	if (mode & S_IXOTH)
698		a6->ae_perm |= ACL_EXECUTE;
699	else
700		a5->ae_perm |= ACL_EXECUTE;
701}
702
703#ifdef _KERNEL
704void
705acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode,
706    int file_owner_id)
707{
708
709	if (acl_nfs4_old_semantics)
710		acl_nfs4_sync_acl_from_mode_draft(aclp, mode, file_owner_id);
711	else
712		acl_nfs4_trivial_from_mode(aclp, mode);
713}
714#endif /* _KERNEL */
715
716void
717acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp)
718{
719	int i;
720	mode_t old_mode = *_mode, mode = 0, seen = 0;
721	const struct acl_entry *entry;
722
723	KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES,
724	    ("aclp->acl_cnt <= ACL_MAX_ENTRIES"));
725
726	/*
727	 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt
728	 *
729	 * 3.16.6.1. Recomputing mode upon SETATTR of ACL
730	 */
731
732	for (i = 0; i < aclp->acl_cnt; i++) {
733		entry = &(aclp->acl_entry[i]);
734
735		if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
736		    entry->ae_entry_type != ACL_ENTRY_TYPE_DENY)
737			continue;
738
739		if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY)
740			continue;
741
742		if (entry->ae_tag == ACL_USER_OBJ) {
743			if ((entry->ae_perm & ACL_READ_DATA) &&
744			    ((seen & S_IRUSR) == 0)) {
745				seen |= S_IRUSR;
746				if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
747					mode |= S_IRUSR;
748			}
749			if ((entry->ae_perm & ACL_WRITE_DATA) &&
750			     ((seen & S_IWUSR) == 0)) {
751				seen |= S_IWUSR;
752				if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
753					mode |= S_IWUSR;
754			}
755			if ((entry->ae_perm & ACL_EXECUTE) &&
756			    ((seen & S_IXUSR) == 0)) {
757				seen |= S_IXUSR;
758				if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
759					mode |= S_IXUSR;
760			}
761		} else if (entry->ae_tag == ACL_GROUP_OBJ) {
762			if ((entry->ae_perm & ACL_READ_DATA) &&
763			    ((seen & S_IRGRP) == 0)) {
764				seen |= S_IRGRP;
765				if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
766					mode |= S_IRGRP;
767			}
768			if ((entry->ae_perm & ACL_WRITE_DATA) &&
769			    ((seen & S_IWGRP) == 0)) {
770				seen |= S_IWGRP;
771				if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
772					mode |= S_IWGRP;
773			}
774			if ((entry->ae_perm & ACL_EXECUTE) &&
775			    ((seen & S_IXGRP) == 0)) {
776				seen |= S_IXGRP;
777				if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
778					mode |= S_IXGRP;
779			}
780		} else if (entry->ae_tag == ACL_EVERYONE) {
781			if (entry->ae_perm & ACL_READ_DATA) {
782				if ((seen & S_IRUSR) == 0) {
783					seen |= S_IRUSR;
784					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
785						mode |= S_IRUSR;
786				}
787				if ((seen & S_IRGRP) == 0) {
788					seen |= S_IRGRP;
789					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
790						mode |= S_IRGRP;
791				}
792				if ((seen & S_IROTH) == 0) {
793					seen |= S_IROTH;
794					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
795						mode |= S_IROTH;
796				}
797			}
798			if (entry->ae_perm & ACL_WRITE_DATA) {
799				if ((seen & S_IWUSR) == 0) {
800					seen |= S_IWUSR;
801					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
802						mode |= S_IWUSR;
803				}
804				if ((seen & S_IWGRP) == 0) {
805					seen |= S_IWGRP;
806					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
807						mode |= S_IWGRP;
808				}
809				if ((seen & S_IWOTH) == 0) {
810					seen |= S_IWOTH;
811					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
812						mode |= S_IWOTH;
813				}
814			}
815			if (entry->ae_perm & ACL_EXECUTE) {
816				if ((seen & S_IXUSR) == 0) {
817					seen |= S_IXUSR;
818					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
819						mode |= S_IXUSR;
820				}
821				if ((seen & S_IXGRP) == 0) {
822					seen |= S_IXGRP;
823					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
824						mode |= S_IXGRP;
825				}
826				if ((seen & S_IXOTH) == 0) {
827					seen |= S_IXOTH;
828					if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
829						mode |= S_IXOTH;
830				}
831			}
832		}
833	}
834
835	*_mode = mode | (old_mode & ACL_PRESERVE_MASK);
836}
837
838#ifdef _KERNEL
839/*
840 * Calculate inherited ACL in a manner compatible with NFSv4 Minor Version 1,
841 * draft-ietf-nfsv4-minorversion1-03.txt.
842 */
843static void
844acl_nfs4_compute_inherited_acl_draft(const struct acl *parent_aclp,
845    struct acl *child_aclp, mode_t mode, int file_owner_id,
846    int is_directory)
847{
848	int i, flags;
849	const struct acl_entry *parent_entry;
850	struct acl_entry *entry, *copy;
851
852	KASSERT(child_aclp->acl_cnt == 0, ("child_aclp->acl_cnt == 0"));
853	KASSERT(parent_aclp->acl_cnt <= ACL_MAX_ENTRIES,
854	    ("parent_aclp->acl_cnt <= ACL_MAX_ENTRIES"));
855
856	/*
857	 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt
858	 *
859	 * 3.16.6.2. Applying the mode given to CREATE or OPEN
860	 *           to an inherited ACL
861	 */
862
863	/*
864	 * 1. Form an ACL that is the concatenation of all inheritable ACEs.
865	 */
866	for (i = 0; i < parent_aclp->acl_cnt; i++) {
867		parent_entry = &(parent_aclp->acl_entry[i]);
868		flags = parent_entry->ae_flags;
869
870		/*
871		 * Entry is not inheritable at all.
872		 */
873		if ((flags & (ACL_ENTRY_DIRECTORY_INHERIT |
874		    ACL_ENTRY_FILE_INHERIT)) == 0)
875			continue;
876
877		/*
878		 * We're creating a file, but entry is not inheritable
879		 * by files.
880		 */
881		if (!is_directory && (flags & ACL_ENTRY_FILE_INHERIT) == 0)
882			continue;
883
884		/*
885		 * Entry is inheritable only by files, but has NO_PROPAGATE
886		 * flag set, and we're creating a directory, so it wouldn't
887		 * propagate to any file in that directory anyway.
888		 */
889		if (is_directory &&
890		    (flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0 &&
891		    (flags & ACL_ENTRY_NO_PROPAGATE_INHERIT))
892			continue;
893
894		KASSERT(child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES,
895		    ("child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES"));
896		child_aclp->acl_entry[child_aclp->acl_cnt] = *parent_entry;
897		child_aclp->acl_cnt++;
898	}
899
900	/*
901	 * 2. For each entry in the new ACL, adjust its flags, possibly
902	 *    creating two entries in place of one.
903	 */
904	for (i = 0; i < child_aclp->acl_cnt; i++) {
905		entry = &(child_aclp->acl_entry[i]);
906
907		/*
908		 * This is not in the specification, but SunOS
909		 * apparently does that.
910		 */
911		if (((entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT) ||
912		    !is_directory) &&
913		    entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
914			entry->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER);
915
916		/*
917		 * 2.A. If the ACL_ENTRY_NO_PROPAGATE_INHERIT is set, or if the object
918		 *      being created is not a directory, then clear the
919		 *      following flags: ACL_ENTRY_NO_PROPAGATE_INHERIT,
920		 *      ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT,
921		 *      ACL_ENTRY_INHERIT_ONLY.
922		 */
923		if (entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT ||
924		    !is_directory) {
925			entry->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT |
926			ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT |
927			ACL_ENTRY_INHERIT_ONLY);
928
929			/*
930			 * Continue on to the next ACE.
931			 */
932			continue;
933		}
934
935		/*
936		 * 2.B. If the object is a directory and ACL_ENTRY_FILE_INHERIT
937		 *      is set, but ACL_ENTRY_NO_PROPAGATE_INHERIT is not set, ensure
938		 *      that ACL_ENTRY_INHERIT_ONLY is set.  Continue to the
939		 *      next ACE.  Otherwise...
940		 */
941		/*
942		 * XXX: Read it again and make sure what does the "otherwise"
943		 *      apply to.
944		 */
945		if (is_directory &&
946		    (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) &&
947		    ((entry->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) {
948			entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
949			continue;
950		}
951
952		/*
953		 * 2.C. If the type of the ACE is neither ALLOW nor deny,
954		 *      then continue.
955		 */
956		if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
957		    entry->ae_entry_type != ACL_ENTRY_TYPE_DENY)
958			continue;
959
960		/*
961		 * 2.D. Copy the original ACE into a second, adjacent ACE.
962		 */
963		copy = _acl_duplicate_entry(child_aclp, i);
964
965		/*
966		 * 2.E. On the first ACE, ensure that ACL_ENTRY_INHERIT_ONLY
967		 *      is set.
968		 */
969		entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
970
971		/*
972		 * 2.F. On the second ACE, clear the following flags:
973		 *      ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_FILE_INHERIT,
974		 *      ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_INHERIT_ONLY.
975		 */
976		copy->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT |
977		    ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT |
978		    ACL_ENTRY_INHERIT_ONLY);
979
980		/*
981		 * 2.G. On the second ACE, if the type is ALLOW,
982		 *      an implementation MAY clear the following
983		 *      mask bits: ACL_WRITE_ACL, ACL_WRITE_OWNER.
984		 */
985		if (copy->ae_entry_type == ACL_ENTRY_TYPE_ALLOW)
986			copy->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER);
987
988		/*
989		 * Increment the counter to skip the copied entry.
990		 */
991		i++;
992	}
993
994	/*
995	 * 3. To ensure that the mode is honored, apply the algorithm describe
996	 *    in Section 2.16.6.3, using the mode that is to be used for file
997	 *    creation.
998	 */
999	acl_nfs4_sync_acl_from_mode(child_aclp, mode, file_owner_id);
1000}
1001#endif /* _KERNEL */
1002
1003/*
1004 * Populate the ACL with entries inherited from parent_aclp.
1005 */
1006static void
1007acl_nfs4_inherit_entries(const struct acl *parent_aclp,
1008    struct acl *child_aclp, mode_t mode, int file_owner_id,
1009    int is_directory)
1010{
1011	int i, flags, tag;
1012	const struct acl_entry *parent_entry;
1013	struct acl_entry *entry;
1014
1015	KASSERT(parent_aclp->acl_cnt <= ACL_MAX_ENTRIES,
1016	    ("parent_aclp->acl_cnt <= ACL_MAX_ENTRIES"));
1017
1018	for (i = 0; i < parent_aclp->acl_cnt; i++) {
1019		parent_entry = &(parent_aclp->acl_entry[i]);
1020		flags = parent_entry->ae_flags;
1021		tag = parent_entry->ae_tag;
1022
1023		/*
1024		 * Don't inherit owner@, group@, or everyone@ entries.
1025		 */
1026		if (tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ ||
1027		    tag == ACL_EVERYONE)
1028			continue;
1029
1030		/*
1031		 * Entry is not inheritable at all.
1032		 */
1033		if ((flags & (ACL_ENTRY_DIRECTORY_INHERIT |
1034		    ACL_ENTRY_FILE_INHERIT)) == 0)
1035			continue;
1036
1037		/*
1038		 * We're creating a file, but entry is not inheritable
1039		 * by files.
1040		 */
1041		if (!is_directory && (flags & ACL_ENTRY_FILE_INHERIT) == 0)
1042			continue;
1043
1044		/*
1045		 * Entry is inheritable only by files, but has NO_PROPAGATE
1046		 * flag set, and we're creating a directory, so it wouldn't
1047		 * propagate to any file in that directory anyway.
1048		 */
1049		if (is_directory &&
1050		    (flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0 &&
1051		    (flags & ACL_ENTRY_NO_PROPAGATE_INHERIT))
1052			continue;
1053
1054		/*
1055		 * Entry qualifies for being inherited.
1056		 */
1057		KASSERT(child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES,
1058		    ("child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES"));
1059		entry = &(child_aclp->acl_entry[child_aclp->acl_cnt]);
1060		*entry = *parent_entry;
1061		child_aclp->acl_cnt++;
1062
1063		entry->ae_flags &= ~ACL_ENTRY_INHERIT_ONLY;
1064		entry->ae_flags |= ACL_ENTRY_INHERITED;
1065
1066		/*
1067		 * If the type of the ACE is neither ALLOW nor DENY,
1068		 * then leave it as it is and proceed to the next one.
1069		 */
1070		if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
1071		    entry->ae_entry_type != ACL_ENTRY_TYPE_DENY)
1072			continue;
1073
1074		/*
1075		 * If the ACL_ENTRY_NO_PROPAGATE_INHERIT is set, or if
1076		 * the object being created is not a directory, then clear
1077		 * the following flags: ACL_ENTRY_NO_PROPAGATE_INHERIT,
1078		 * ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT,
1079		 * ACL_ENTRY_INHERIT_ONLY.
1080		 */
1081		if (entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT ||
1082		    !is_directory) {
1083			entry->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT |
1084			ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT |
1085			ACL_ENTRY_INHERIT_ONLY);
1086		}
1087
1088		/*
1089		 * If the object is a directory and ACL_ENTRY_FILE_INHERIT
1090		 * is set, but ACL_ENTRY_DIRECTORY_INHERIT is not set, ensure
1091		 * that ACL_ENTRY_INHERIT_ONLY is set.
1092		 */
1093		if (is_directory &&
1094		    (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) &&
1095		    ((entry->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) {
1096			entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY;
1097		}
1098
1099		if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW &&
1100		    (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) == 0) {
1101			/*
1102			 * Some permissions must never be inherited.
1103			 */
1104			entry->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER |
1105			    ACL_WRITE_NAMED_ATTRS | ACL_WRITE_ATTRIBUTES);
1106
1107			/*
1108			 * Others must be masked according to the file mode.
1109			 */
1110			if ((mode & S_IRGRP) == 0)
1111				entry->ae_perm &= ~ACL_READ_DATA;
1112			if ((mode & S_IWGRP) == 0)
1113				entry->ae_perm &=
1114				    ~(ACL_WRITE_DATA | ACL_APPEND_DATA);
1115			if ((mode & S_IXGRP) == 0)
1116				entry->ae_perm &= ~ACL_EXECUTE;
1117		}
1118	}
1119}
1120
1121/*
1122 * Calculate inherited ACL in a manner compatible with PSARC/2010/029.
1123 * It's also being used to calculate a trivial ACL, by inheriting from
1124 * a NULL ACL.
1125 */
1126static void
1127acl_nfs4_compute_inherited_acl_psarc(const struct acl *parent_aclp,
1128    struct acl *aclp, mode_t mode, int file_owner_id, int is_directory)
1129{
1130	acl_perm_t user_allow_first = 0, user_deny = 0, group_deny = 0;
1131	acl_perm_t user_allow, group_allow, everyone_allow;
1132
1133	KASSERT(aclp->acl_cnt == 0, ("aclp->acl_cnt == 0"));
1134
1135	user_allow = group_allow = everyone_allow = ACL_READ_ACL |
1136	    ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | ACL_SYNCHRONIZE;
1137	user_allow |= ACL_WRITE_ACL | ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES |
1138	    ACL_WRITE_NAMED_ATTRS;
1139
1140	if (mode & S_IRUSR)
1141		user_allow |= ACL_READ_DATA;
1142	if (mode & S_IWUSR)
1143		user_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
1144	if (mode & S_IXUSR)
1145		user_allow |= ACL_EXECUTE;
1146
1147	if (mode & S_IRGRP)
1148		group_allow |= ACL_READ_DATA;
1149	if (mode & S_IWGRP)
1150		group_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
1151	if (mode & S_IXGRP)
1152		group_allow |= ACL_EXECUTE;
1153
1154	if (mode & S_IROTH)
1155		everyone_allow |= ACL_READ_DATA;
1156	if (mode & S_IWOTH)
1157		everyone_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA);
1158	if (mode & S_IXOTH)
1159		everyone_allow |= ACL_EXECUTE;
1160
1161	user_deny = ((group_allow | everyone_allow) & ~user_allow);
1162	group_deny = everyone_allow & ~group_allow;
1163	user_allow_first = group_deny & ~user_deny;
1164
1165	if (user_allow_first != 0)
1166		_acl_append(aclp, ACL_USER_OBJ, user_allow_first,
1167		    ACL_ENTRY_TYPE_ALLOW);
1168	if (user_deny != 0)
1169		_acl_append(aclp, ACL_USER_OBJ, user_deny,
1170		    ACL_ENTRY_TYPE_DENY);
1171	if (group_deny != 0)
1172		_acl_append(aclp, ACL_GROUP_OBJ, group_deny,
1173		    ACL_ENTRY_TYPE_DENY);
1174
1175	if (parent_aclp != NULL)
1176		acl_nfs4_inherit_entries(parent_aclp, aclp, mode,
1177		    file_owner_id, is_directory);
1178
1179	_acl_append(aclp, ACL_USER_OBJ, user_allow, ACL_ENTRY_TYPE_ALLOW);
1180	_acl_append(aclp, ACL_GROUP_OBJ, group_allow, ACL_ENTRY_TYPE_ALLOW);
1181	_acl_append(aclp, ACL_EVERYONE, everyone_allow, ACL_ENTRY_TYPE_ALLOW);
1182}
1183
1184#ifdef _KERNEL
1185void
1186acl_nfs4_compute_inherited_acl(const struct acl *parent_aclp,
1187    struct acl *child_aclp, mode_t mode, int file_owner_id,
1188    int is_directory)
1189{
1190
1191	if (acl_nfs4_old_semantics)
1192		acl_nfs4_compute_inherited_acl_draft(parent_aclp, child_aclp,
1193		    mode, file_owner_id, is_directory);
1194	else
1195		acl_nfs4_compute_inherited_acl_psarc(parent_aclp, child_aclp,
1196		    mode, file_owner_id, is_directory);
1197}
1198#endif /* _KERNEL */
1199
1200/*
1201 * Calculate trivial ACL in a manner compatible with PSARC/2010/029.
1202 * Note that this results in an ACL different from (but semantically
1203 * equal to) the "canonical six" trivial ACL computed using algorithm
1204 * described in draft-ietf-nfsv4-minorversion1-03.txt, 3.16.6.2.
1205 */
1206static void
1207acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode)
1208{
1209
1210	aclp->acl_cnt = 0;
1211	acl_nfs4_compute_inherited_acl_psarc(NULL, aclp, mode, -1, -1);
1212}
1213
1214#ifndef _KERNEL
1215/*
1216 * This routine is used by libc to implement acl_strip_np(3)
1217 * and acl_is_trivial_np(3).
1218 */
1219void
1220acl_nfs4_trivial_from_mode_libc(struct acl *aclp, int mode, int canonical_six)
1221{
1222
1223	aclp->acl_cnt = 0;
1224	if (canonical_six)
1225		acl_nfs4_sync_acl_from_mode_draft(aclp, mode, -1);
1226	else
1227		acl_nfs4_trivial_from_mode(aclp, mode);
1228}
1229#endif /* !_KERNEL */
1230
1231#ifdef _KERNEL
1232static int
1233_acls_are_equal(const struct acl *a, const struct acl *b)
1234{
1235	int i;
1236	const struct acl_entry *entrya, *entryb;
1237
1238	if (a->acl_cnt != b->acl_cnt)
1239		return (0);
1240
1241	for (i = 0; i < b->acl_cnt; i++) {
1242		entrya = &(a->acl_entry[i]);
1243		entryb = &(b->acl_entry[i]);
1244
1245		if (entrya->ae_tag != entryb->ae_tag ||
1246		    entrya->ae_id != entryb->ae_id ||
1247		    entrya->ae_perm != entryb->ae_perm ||
1248		    entrya->ae_entry_type != entryb->ae_entry_type ||
1249		    entrya->ae_flags != entryb->ae_flags)
1250			return (0);
1251	}
1252
1253	return (1);
1254}
1255
1256/*
1257 * This routine is used to determine whether to remove extended attribute
1258 * that stores ACL contents.
1259 */
1260int
1261acl_nfs4_is_trivial(const struct acl *aclp, int file_owner_id)
1262{
1263	int trivial;
1264	mode_t tmpmode = 0;
1265	struct acl *tmpaclp;
1266
1267	if (aclp->acl_cnt > 6)
1268		return (0);
1269
1270	/*
1271	 * Compute the mode from the ACL, then compute new ACL from that mode.
1272	 * If the ACLs are identical, then the ACL is trivial.
1273	 *
1274	 * XXX: I guess there is a faster way to do this.  However, even
1275	 *      this slow implementation significantly speeds things up
1276	 *      for files that don't have non-trivial ACLs - it's critical
1277	 *      for performance to not use EA when they are not needed.
1278	 *
1279	 * First try the PSARC/2010/029 semantics.
1280	 */
1281	tmpaclp = acl_alloc(M_WAITOK | M_ZERO);
1282	acl_nfs4_sync_mode_from_acl(&tmpmode, aclp);
1283	acl_nfs4_trivial_from_mode(tmpaclp, tmpmode);
1284	trivial = _acls_are_equal(aclp, tmpaclp);
1285	if (trivial) {
1286		acl_free(tmpaclp);
1287		return (trivial);
1288	}
1289
1290	/*
1291	 * Check if it's a draft-ietf-nfsv4-minorversion1-03.txt trivial ACL.
1292	 */
1293	tmpaclp->acl_cnt = 0;
1294	acl_nfs4_sync_acl_from_mode_draft(tmpaclp, tmpmode, file_owner_id);
1295	trivial = _acls_are_equal(aclp, tmpaclp);
1296	acl_free(tmpaclp);
1297
1298	return (trivial);
1299}
1300#endif /* _KERNEL */
1301
1302int
1303acl_nfs4_check(const struct acl *aclp, int is_directory)
1304{
1305	int i;
1306	const struct acl_entry *entry;
1307
1308	/*
1309	 * The spec doesn't seem to say anything about ACL validity.
1310	 * It seems there is not much to do here.  There is even no need
1311	 * to count "owner@" or "everyone@" (ACL_USER_OBJ and ACL_EVERYONE)
1312	 * entries, as there can be several of them and that's perfectly
1313	 * valid.  There can be none of them too.  Really.
1314	 */
1315
1316	if (aclp->acl_cnt > ACL_MAX_ENTRIES || aclp->acl_cnt <= 0)
1317		return (EINVAL);
1318
1319	for (i = 0; i < aclp->acl_cnt; i++) {
1320		entry = &(aclp->acl_entry[i]);
1321
1322		switch (entry->ae_tag) {
1323		case ACL_USER_OBJ:
1324		case ACL_GROUP_OBJ:
1325		case ACL_EVERYONE:
1326			if (entry->ae_id != ACL_UNDEFINED_ID)
1327				return (EINVAL);
1328			break;
1329
1330		case ACL_USER:
1331		case ACL_GROUP:
1332			if (entry->ae_id == ACL_UNDEFINED_ID)
1333				return (EINVAL);
1334			break;
1335
1336		default:
1337			return (EINVAL);
1338		}
1339
1340		if ((entry->ae_perm | ACL_NFS4_PERM_BITS) != ACL_NFS4_PERM_BITS)
1341			return (EINVAL);
1342
1343		/*
1344		 * Disallow ACL_ENTRY_TYPE_AUDIT and ACL_ENTRY_TYPE_ALARM for now.
1345		 */
1346		if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
1347		    entry->ae_entry_type != ACL_ENTRY_TYPE_DENY)
1348			return (EINVAL);
1349
1350		if ((entry->ae_flags | ACL_FLAGS_BITS) != ACL_FLAGS_BITS)
1351			return (EINVAL);
1352
1353		/* Disallow unimplemented flags. */
1354		if (entry->ae_flags & (ACL_ENTRY_SUCCESSFUL_ACCESS |
1355		    ACL_ENTRY_FAILED_ACCESS))
1356			return (EINVAL);
1357
1358		/* Disallow flags not allowed for ordinary files. */
1359		if (!is_directory) {
1360			if (entry->ae_flags & (ACL_ENTRY_FILE_INHERIT |
1361			    ACL_ENTRY_DIRECTORY_INHERIT |
1362			    ACL_ENTRY_NO_PROPAGATE_INHERIT | ACL_ENTRY_INHERIT_ONLY))
1363				return (EINVAL);
1364		}
1365	}
1366
1367	return (0);
1368}
1369
1370#ifdef	_KERNEL
1371static int
1372acl_nfs4_modload(module_t module, int what, void *arg)
1373{
1374	int ret;
1375
1376	ret = 0;
1377
1378	switch (what) {
1379	case MOD_LOAD:
1380	case MOD_SHUTDOWN:
1381		break;
1382
1383	case MOD_QUIESCE:
1384		/* XXX TODO */
1385		ret = 0;
1386		break;
1387
1388	case MOD_UNLOAD:
1389		/* XXX TODO */
1390		ret = 0;
1391		break;
1392	default:
1393		ret = EINVAL;
1394		break;
1395	}
1396
1397	return (ret);
1398}
1399
1400static moduledata_t acl_nfs4_mod = {
1401	"acl_nfs4",
1402	acl_nfs4_modload,
1403	NULL
1404};
1405
1406/*
1407 * XXX TODO: which subsystem, order?
1408 */
1409DECLARE_MODULE(acl_nfs4, acl_nfs4_mod, SI_SUB_VFS, SI_ORDER_FIRST);
1410MODULE_VERSION(acl_nfs4, 1);
1411#endif	/* _KERNEL */
1412