1/*
2 *	Aurélien Charbon - Bull SA
3 *	ACL testing basic program
4 *	Purpose: setting an acl on a file a verifies that the accesses are right
5 */
6
7#include <sys/param.h>
8
9#include <stdlib.h>
10#include <sys/types.h>
11#include <sys/time.h>
12#include <sys/stat.h>
13#include <stdio.h>
14#include <string.h>
15#include <dirent.h>
16#include <unistd.h>
17#include <errno.h>
18
19#include "config.h"
20#include "tst_res_flags.h"
21
22#ifdef HAVE_LIBACL
23
24#include <sys/acl.h>
25
26#define OP_READ 0x1
27#define OP_WRITE 0x2
28#define OP_EXEC 0x4
29
30acl_t testacl;
31/* the "typical" acl used for the test */
32
33static char *permtab[] =
34    { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" };
35
36struct statstore {
37	/* number of passed tests */
38	int ok;
39	/* number of failed tests */
40	int failed;
41} aclstat;
42
43int do_file_op(char *filename)
44{
45	int exe;
46	int result;
47	uid_t uid;
48	result = 0;
49	FILE *fptr;
50	char str[256] = "./";
51
52	uid = geteuid();
53	strcat(str, filename);
54
55	exe = execl(str, NULL, NULL);
56	if (exe == -1 && errno != EACCES)
57		result = result + OP_EXEC;
58
59	fptr = fopen(filename, "r");
60	if (fptr != NULL) {
61		result = result + OP_READ;
62		fclose(fptr);
63	}
64
65	fptr = fopen(filename, "r+");
66	if (fptr != NULL) {
67		result = result + OP_WRITE;
68		fclose(fptr);
69	}
70
71	return result;
72}
73
74/*  acl with user entries used for the test */
75acl_t test_acl_user_create(void)
76{
77	char acl_text[] =
78	    "u::rwx,u:user1:rwx,u:user2:rw-,u:user3:r--,u:user4:r-x,u:user5:---,g::r-x,o::r-x,m::rwx";
79	acl_t acl;
80	acl = acl_from_text(acl_text);
81	return acl;
82}
83
84/*  acl with group entries used for the test */
85
86acl_t test_acl_grp_create(void)
87{
88	char acl_text[] =
89	    "u::rwx,g:grp1:rwx,g:grp2:rw-,g:grp3:r--,g:grp4:r-x,g:grp5:---,g::---,o::r-x,m::rwx";
90	acl_t acl;
91	acl = acl_from_text(acl_text);
92	return acl;
93}
94
95acl_t test_acl_default_create(void)
96{
97	char acl_text[] =
98	    "u::rwx,u:user1:rwx,u:user2:rw-,u:user3:r--,u:user4:r-x,u:user5:---,g::r-x,m::rwx,o::r-x";
99	acl_t acl;
100	acl = acl_from_text(acl_text);
101	return acl;
102}
103
104static void report(testnum, expected, result, fail)
105int testnum;			/* test number */
106int expected;			/* expected result */
107int result;			/* actual result */
108int fail;			/* fail or warning */
109{
110	char *res;
111	if (expected == result) {
112		res = "[OK]";
113		aclstat.ok++;
114	} else {
115		res = "[FAILED]";
116		aclstat.failed++;
117	}
118	printf("\ttest #%d - Expected: %s - Obtained: %s - %s\n", testnum,
119	       permtab[expected], permtab[result], res);
120
121	fflush(stdout);
122}
123
124/*
125 * set acl in order the file is only readable for the testuser
126 * - try to read
127 * - try to write
128 */
129static void test1(char *file)
130{
131	int result;
132	if (seteuid((uid_t) 601) == 0) {
133		result = do_file_op(file);
134		/* expected result = OP_READ || OP_WRITE || OP_EXEC */
135		report(1, OP_READ + OP_WRITE + OP_EXEC, result);
136		seteuid((uid_t) 0);
137		setegid((gid_t) 0);
138	}
139}
140
141/*
142 * set acl in order the file is only readable for the testgroup
143 * - try to read with test user
144 * - try to write with test user
145 *
146 */
147
148static void test2(char *file)
149{
150	int result;
151	if (seteuid((uid_t) 602) == 0) {
152		result = do_file_op(file);
153		/* expected result = OP_READ || OP_WRITE */
154		report(2, OP_READ + OP_WRITE, result);
155		seteuid((uid_t) 0);
156	}
157}
158
159/*
160 * set acl in order the file is only readable for the testuser
161 * - try to read
162 * - try to write
163 */
164
165static void test3(char *file)
166{
167	int result;
168	if (seteuid((uid_t) 603) == 0) {
169		result = do_file_op(file);
170		/* expected result = OP_READ */
171		report(3, OP_READ, result);
172		seteuid((uid_t) 0);
173	}
174}
175
176/*
177 * set read-write acl on the file for the testuser
178 * - try to read
179 * - try to write
180 */
181
182static void test4(char *file)
183{
184	int result;
185	if (seteuid((uid_t) 604) == 0) {
186		result = do_file_op(file);
187		/* expected result = OP_READ || OP_EXEC */
188		report(4, OP_READ + OP_EXEC, result);
189		seteuid((uid_t) 0);
190	}
191}
192
193static void test5(char *file)
194{
195	int result;
196	if (seteuid((uid_t) 605) == 0) {
197		result = do_file_op(file);
198		/* expected result = 0x0 */
199		report(5, 0x00, result);
200		seteuid((uid_t) 0);
201	}
202}
203
204static void testgrp1(char *file)
205{
206	int result;
207	if (setegid((gid_t) 601) == 0) {
208		if (seteuid((uid_t) 601) == 0) {
209			result = do_file_op(file);
210			/* expected result = OP_READ || OP_WRITE || OP_EXEC */
211			report(1, OP_READ + OP_WRITE + OP_EXEC, result);
212			seteuid((uid_t) 0);
213			setegid((gid_t) 0);
214		}
215	}
216}
217
218/*
219 * set acl in order the file is only readable for the testgroup
220 * - try to read with test user
221 * - try to write with test user
222 *
223 */
224
225static void testgrp2(char *file)
226{
227	int result;
228	if ((setegid((gid_t) 602) == 0) && (seteuid((uid_t) 602) == 0)) {
229		result = do_file_op(file);
230		/* expected result = OP_READ || OP_WRITE */
231		report(2, OP_READ + OP_WRITE, result);
232		seteuid((uid_t) 0);
233		setegid((gid_t) 0);
234	}
235}
236
237/*
238 * set acl in order the file is only readable for the testuser
239 * - try to read
240 * - try to write
241 */
242
243static void testgrp3(char *file)
244{
245	int result;
246	if ((setegid((gid_t) 603) == 0) && (seteuid((uid_t) 603) == 0)) {
247		result = do_file_op(file);
248		/* expected result = OP_READ */
249		report(3, OP_READ, result);
250		seteuid((uid_t) 0);
251		setegid((gid_t) 0);
252	}
253}
254
255/*
256 * set read-write acl on the file for the testuser
257 * - try to read
258 * - try to write
259 */
260
261static void testgrp4(char *file)
262{
263	int result;
264	if (setegid((gid_t) 604) == 0) {
265		if (seteuid((uid_t) 604) == 0)
266			result = do_file_op(file);
267		/* expected result = OP_READ || OP_EXEC */
268		report(4, OP_READ + OP_EXEC, result);
269		seteuid((uid_t) 0);
270		setegid((gid_t) 0);
271	}
272}
273
274static void testgrp5(char *file)
275{
276	int result;
277	if (setegid((gid_t) 605) == 0) {
278		if (seteuid((uid_t) 605) == 0)
279			result = do_file_op(file);
280		/* expected result = 0x0 */
281		report(5, 0x00, result);
282		seteuid((uid_t) 0);
283		setegid((gid_t) 0);
284	}
285}
286
287/* testing default acl */
288void test_acl_default(char *dir, acl_t acl)
289{
290	/* set default acl on directory */
291	/* create a file in this directory */
292	/* compare the file's acl and the parent directory's one */
293	int res;
294	acl_t acl1, acl2;
295
296	res = acl_set_file(dir, ACL_TYPE_DEFAULT, acl);
297	acl1 = acl_get_file(dir, ACL_TYPE_DEFAULT);
298	if (res == -1)
299		printf("path = %s **** errno = %d", dir, errno);
300	char *path = strcat(dir, "/testfile");
301	fopen(path, "w+");
302	char *cmd = malloc(256);
303
304	strcpy(cmd, "chmod 7777 ");
305	printf(cmd, NULL);
306	strcat(cmd, dir);
307	system(cmd);
308	acl2 = acl_get_file(path, ACL_TYPE_ACCESS);
309
310	test1(path);
311	test2(path);
312	test3(path);
313	test4(path);
314	test5(path);
315}
316
317static void showstats(void)
318{
319	printf("\nACL TESTS RESULTS: %d passed, %d failed\n\n", aclstat.ok,
320	       aclstat.failed);
321}
322
323int main(int argc, char *argv[])
324{
325	int result;
326	aclstat.ok = 0;
327	aclstat.failed = 0;
328	acl_t testacl;
329	printf("Test acl with entries on users\n");
330	testacl = test_acl_user_create();
331
332	/* set the right acl for the test */
333	result = acl_set_file(argv[1], ACL_TYPE_ACCESS, testacl);
334	if (result == -1) {
335		printf("setting acl on file %s failed\nBad NFS configuration",
336		       argv[1]);
337		exit(1);
338	}
339	test1(argv[1]);
340	test2(argv[1]);
341	test3(argv[1]);
342	test4(argv[1]);
343	test5(argv[1]);
344	acl_free(testacl);
345	printf("\nTest of default acl:\n");
346
347	testacl = test_acl_default_create();
348	test_acl_default(argv[2], testacl);
349
350	printf("\nTest acl with entries concerning groups\n");
351	testacl = test_acl_grp_create();
352	result = acl_set_file(argv[1], ACL_TYPE_ACCESS, testacl);
353	if (result == -1)
354		printf("setting acl on file %s failed\n", argv[1]);
355
356	testgrp1(argv[1]);
357	testgrp2(argv[1]);
358	testgrp3(argv[1]);
359	testgrp4(argv[1]);
360	testgrp5(argv[1]);
361
362	acl_free(testacl);
363
364	showstats();
365	return 1;
366}
367#else
368int main(void)
369{
370	printf("The acl library was missing upon compilation.\n");
371	return TCONF;
372}
373#endif /* HAVE_LIBACL */
374