xref: /illumos-gate/usr/src/cmd/filesync/acls.c (revision 7c478bd9)
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