1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved
24 *
25 * module:
26 * acls.c
27 *
28 * purpose:
29 * routines to manipulate access control lists, mapping between
30 * the data structures required by the filesystem ACL system calls
31 * and the representation used in our fileinfo structure.
32 *
33 */
34 #ident "%W% %E% SMI"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #include "filesync.h"
40 #include "database.h"
41
42 #ifdef NO_ACLS
43 /*
44 * Solaris 2.4 libc.so does not contain this entry point, so if we
45 * want to build a 2.4 version of filesync, we need to provide a
46 * dummy entry point that will fail when-ever it is called.
47 */
48 #define acl bogus_acl
49
acl(const char * name,int opcode,int count,aclent_t * acls)50 static int acl(const char *name, int opcode, int count, aclent_t *acls)
51 {
52 return (-1);
53 }
54 #endif
55
56 /*
57 * routine:
58 * get_acls
59 *
60 * purpose:
61 * to read the ACL (if any) from a file into a fileinfo structure
62 *
63 * parameters:
64 * name of file
65 * pointer to fileinfo structure
66 *
67 * returns:
68 * number of ACL entries
69 */
70 int
get_acls(const char * name,struct fileinfo * ip)71 get_acls(const char *name, struct fileinfo *ip)
72 { int count;
73 int i;
74 static aclent_t acls[MAX_ACL_ENTRIES];
75 aclent_t *list;
76
77 count = acl(name, GETACL, MAX_ACL_ENTRIES, acls);
78 if (count <= 0)
79 return (0);
80
81 /* with a count of 3 or 4 there may not be any real ones */
82 if (count > 4)
83 goto gotsome;
84
85 /* look for anything beyond the normal unix protection */
86 for (i = 0; i < count; i++)
87 switch (acls[i].a_type) {
88 default: /* weird types are real */
89 goto gotsome;
90
91 case USER_OBJ:
92 case GROUP_OBJ:
93 case OTHER_OBJ:
94 case CLASS_OBJ:
95 continue; /* all file have these */
96 }
97
98 return (0); /* nothing interesting */
99
100 gotsome:
101 /* allocate an array to hold the acls */
102 list = (aclent_t *) malloc(count * sizeof (*list));
103 if (list == 0)
104 nomem("Access Control List");
105
106 /* copy the acls into the new list */
107 for (i = 0; i < count; i++) {
108 list[i].a_type = acls[i].a_type;
109 list[i].a_id = acls[i].a_id;
110 list[i].a_perm = acls[i].a_perm;
111 }
112
113 ip->f_acls = list;
114 ip->f_numacls = count;
115 return (ip->f_numacls);
116 }
117
118 /*
119 * routine:
120 * cmp_acls
121 *
122 * purpose:
123 * determine whether or not two ACLs are the same
124 *
125 * parameters:
126 * pointer to first fileinfo
127 * pointer to second fileinfo
128 *
129 * returns:
130 * true equal
131 * false different
132 */
133 int
cmp_acls(struct fileinfo * f1,struct fileinfo * f2)134 cmp_acls(struct fileinfo *f1, struct fileinfo *f2)
135 { int i;
136
137 if (f1->f_numacls != f2->f_numacls)
138 return (0);
139
140 if (f1->f_numacls == 0)
141 return (1);
142
143 for (i = 0; i < f1->f_numacls; i++) {
144 if (f1->f_acls[i].a_type != f2->f_acls[i].a_type)
145 return (0);
146 if (f1->f_acls[i].a_id != f2->f_acls[i].a_id)
147 return (0);
148 if (f1->f_acls[i].a_perm != f2->f_acls[i].a_perm)
149 return (0);
150 }
151
152 return (1);
153 }
154
155 /*
156 * routine:
157 * set_acls
158 *
159 * purpose:
160 * to write the ACL of a file
161 *
162 * parameters:
163 * name of file
164 * fileinfo pointer (which contains an acl pointer)
165 *
166 * returns:
167 * retcode and errno
168 */
169 int
set_acls(const char * name,struct fileinfo * fp)170 set_acls(const char *name, struct fileinfo *fp)
171 { int rc;
172 int nacl;
173 aclent_t acls[4], *list;
174
175 if (fp->f_numacls == 0) {
176 /* fabricate a standard set of bogus ACLs */
177 acls[0].a_type = USER_OBJ;
178 acls[0].a_id = fp->f_uid;
179 acls[0].a_perm = (fp->f_mode >> 6) & 7;
180
181 acls[1].a_type = GROUP_OBJ;
182 acls[1].a_id = fp->f_gid;
183 acls[1].a_perm = (fp->f_mode >> 3) & 7;
184
185 acls[2].a_type = CLASS_OBJ;
186 acls[2].a_id = 0;
187 acls[2].a_perm = (fp->f_mode >> 6) & 7;
188
189 acls[3].a_type = OTHER_OBJ;
190 acls[3].a_id = 0;
191 acls[3].a_perm = fp->f_mode & 7;
192
193 nacl = 4;
194 list = acls;
195 } else {
196 nacl = fp->f_numacls;
197 list = fp->f_acls;
198 }
199
200 rc = acl(name, SETACL, nacl, list);
201
202 /* non-negative number mean success */
203 if (rc < 0)
204 return (rc);
205 else
206 return (0);
207 }
208
209 /*
210 * routine:
211 * show_acls
212 *
213 * purpose:
214 * to map an acl into arguments for a setfacl command
215 *
216 * paramters:
217 * number of elements in list
218 * pointer to list
219 *
220 * returns:
221 * pointer to character buffer containing arguments
222 */
223 char
show_acls(int numacl,aclent_t * list)224 *show_acls(int numacl, aclent_t *list)
225 { int i, j;
226 int type, perm, id;
227 char *s;
228 static char buf[ MAX_LINE ];
229
230 s = buf;
231
232 if (numacl > 0) {
233 *s++ = '-';
234 *s++ = 's';
235 *s++ = ' ';
236 } else {
237 *s++ = '-';
238 *s++ = 'd';
239 }
240
241 for (i = 0; i < numacl; i++) {
242 type = list[i].a_type;
243 id = list[i].a_id;
244 perm = list[i].a_perm;
245
246 if (i > 0)
247 *s++ = ',';
248
249 /* note whether this is per-file or default */
250 if (type & ACL_DEFAULT) {
251 *s++ = 'd';
252 *s++ = ':';
253 }
254
255 /* print out the entry type */
256 if (type & (USER_OBJ|USER)) {
257 *s++ = 'u';
258 *s++ = ':';
259 } else if (type & (GROUP_OBJ|GROUP)) {
260 *s++ = 'g';
261 *s++ = ':';
262 } else if (type & OTHER_OBJ) {
263 *s++ = 'o';
264 *s++ = ':';
265 } else if (type & CLASS_OBJ) {
266 *s++ = 'm';
267 *s++ = ':';
268 }
269
270 /* print out the ID for this ACL */
271 if (type & (USER_OBJ|GROUP_OBJ))
272 *s++ = ':';
273 else if (type & (USER|GROUP)) {
274 for (j = 1; id/j > 10; j *= 10);
275
276 while (j > 0) {
277 *s++ = '0' + (id/j);
278 id %= j*10;
279 j /= 10;
280 }
281
282 *s++ = ':';
283 }
284
285 /* print out the permissions for this ACL */
286 *s++ = (perm & 04) ? 'r' : '-';
287 *s++ = (perm & 02) ? 'w' : '-';
288 *s++ = (perm & 01) ? 'x' : '-';
289 }
290
291 *s = 0;
292 return (buf);
293 }
294