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