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