]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libc/posix1e/acl_strip.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libc / posix1e / acl_strip.c
1 /*-
2  * Copyright (c) 2001 Chris D. Faulhaber
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 THE VOICES IN HIS HEAD BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <errno.h>
31 #include <stdio.h>
32 #include <assert.h>
33 #include <sys/acl.h>
34
35 #include "acl_support.h"
36
37 /*
38  * These two routines from sys/kern/subr_acl_nfs4.c are used by both kernel
39  * and libc.
40  */
41 void    acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode,
42             int file_owner_id);
43 void    acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp);
44
45 static acl_t
46 _nfs4_acl_strip_np(const acl_t aclp, int recalculate_mask)
47 {
48         acl_t newacl;
49         mode_t mode = 0;
50
51         newacl = acl_init(ACL_MAX_ENTRIES);
52         if (newacl == NULL) {
53                 errno = ENOMEM;
54                 return (NULL);
55         }
56
57         _acl_brand_as(newacl, ACL_BRAND_NFS4);
58
59         acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl));
60         acl_nfs4_sync_acl_from_mode(&(newacl->ats_acl), mode, -1);
61
62         return (newacl);
63 }
64
65 static acl_t
66 _posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
67 {
68         acl_t acl_new, acl_old;
69         acl_entry_t entry, entry_new;
70         acl_permset_t perm;
71         acl_tag_t tag;
72         int entry_id, have_mask_entry;
73
74         assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
75
76         acl_old = acl_dup(aclp);
77         if (acl_old == NULL)
78                 return (NULL);
79
80         assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);
81
82         have_mask_entry = 0;
83         acl_new = acl_init(ACL_MAX_ENTRIES);
84         if (acl_new == NULL)
85                 return (NULL);
86         tag = ACL_UNDEFINED_TAG;
87
88         /* only save the default user/group/other entries */
89         entry_id = ACL_FIRST_ENTRY;
90         while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
91                 entry_id = ACL_NEXT_ENTRY;
92
93                 assert(_entry_brand(entry) == ACL_BRAND_POSIX);
94
95                 if (acl_get_tag_type(entry, &tag) == -1)
96                         return (NULL);
97
98                 switch(tag) {
99                 case ACL_USER_OBJ:
100                 case ACL_GROUP_OBJ:
101                 case ACL_OTHER:
102                         if (acl_get_tag_type(entry, &tag) == -1)
103                                 return (NULL);
104                         if (acl_get_permset(entry, &perm) == -1)
105                                 return (NULL);
106                         if (acl_create_entry(&acl_new, &entry_new) == -1)
107                                 return (NULL);
108                         if (acl_set_tag_type(entry_new, tag) == -1)
109                                 return (NULL);
110                         if (acl_set_permset(entry_new, perm) == -1)
111                                 return (NULL);
112                         if (acl_copy_entry(entry_new, entry) == -1)
113                                 return (NULL);
114                         assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
115                         break;
116                 case ACL_MASK:
117                         have_mask_entry = 1;
118                         break;
119                 default:
120                         break;
121                 }
122         }
123
124         assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);
125
126         if (have_mask_entry && recalculate_mask) {
127                 if (acl_calc_mask(&acl_new) == -1)
128                         return (NULL);
129         }
130
131         return (acl_new);
132 }
133
134 acl_t
135 acl_strip_np(const acl_t aclp, int recalculate_mask)
136 {
137         switch (_acl_brand(aclp)) {
138         case ACL_BRAND_NFS4:
139                 return (_nfs4_acl_strip_np(aclp, recalculate_mask));
140
141         case ACL_BRAND_POSIX:
142                 return (_posix1e_acl_strip_np(aclp, recalculate_mask));
143
144         default:
145                 errno = EINVAL;
146                 return (NULL);
147         }
148 }
149
150 /*
151  * Return 1, if ACL is trivial, 0 otherwise.
152  *
153  * ACL is trivial, iff its meaning could be fully expressed using just file
154  * mode.  In other words, ACL is trivial iff it doesn't have "+" to the right
155  * of the mode bits in "ls -l" output ;-)
156  */
157 int
158 acl_is_trivial_np(const acl_t aclp, int *trivialp)
159 {
160         acl_t tmpacl;
161         int differs;
162
163         if (aclp == NULL || trivialp == NULL) {
164                 errno = EINVAL;
165                 return (-1);
166         }
167
168         switch (_acl_brand(aclp)) {
169         case ACL_BRAND_POSIX:
170                 if (aclp->ats_acl.acl_cnt == 3)
171                         *trivialp = 1;
172                 else
173                         *trivialp = 0;
174
175                 return (0);
176
177         case ACL_BRAND_NFS4:
178                 /*
179                  * Calculate trivial ACL - using acl_strip_np - and compare
180                  * with the original.
181                  */
182                 tmpacl = acl_strip_np(aclp, 0);
183                 if (tmpacl == NULL)
184                         return (-1);
185
186                 differs = _acl_differs(aclp, tmpacl);
187                 acl_free(tmpacl);
188
189                 if (differs)
190                         *trivialp = 0;
191                 else
192                         *trivialp = 1;
193
194                 return (0);
195
196         default:
197                 errno = EINVAL;
198                 return (-1);
199         }
200 }