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