xref: /freebsd/lib/libcasper/services/cap_fileargs/tests/fileargs_test.c (revision 58a08f9e9910ea986e0f1103f47274a781b11874)
1 /*-
2  * Copyright (c) 2021 Mariusz Zaborski <oshogbo@FreeBSD.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
14  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
15  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23  * POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include <sys/param.h>
30 #include <sys/capsicum.h>
31 #include <sys/stat.h>
32 
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <stdio.h>
36 
37 #include <atf-c.h>
38 
39 #include <libcasper.h>
40 #include <casper/cap_fileargs.h>
41 
42 #define MAX_FILES		200
43 
44 static char *files[MAX_FILES];
45 static int fds[MAX_FILES];
46 
47 #define	TEST_FILE	"/etc/passwd"
48 
49 static void
50 prepare_files(size_t num, bool create)
51 {
52 	const char template[] = "testsfiles.XXXXXXXX";
53 	size_t i;
54 
55 	for (i = 0; i < num; i++) {
56 		files[i] = calloc(1, sizeof(template));
57 		ATF_REQUIRE(files[i] != NULL);
58 		strncpy(files[i], template, sizeof(template) - 1);
59 
60 		if (create) {
61 			fds[i] = mkstemp(files[i]);
62 			ATF_REQUIRE(fds[i] >= 0);
63 		} else {
64 			fds[i] = -1;
65 			ATF_REQUIRE(mktemp(files[i]) != NULL);
66 		}
67 	}
68 }
69 
70 static void
71 clear_files(void)
72 {
73 	size_t i;
74 
75 
76 	for (i = 0; files[i] != NULL; i++) {
77 		unlink(files[i]);
78 		free(files[i]);
79 		if (fds[i] != -1)
80 			close(fds[i]);
81 	}
82 }
83 
84 static int
85 test_file_open(fileargs_t *fa, const char *file, int *fdp)
86 {
87 	int fd;
88 
89 	fd = fileargs_open(fa, file);
90 	if (fd < 0)
91 		return (errno);
92 
93 	if (fdp != NULL) {
94 		*fdp = fd;
95 	}
96 
97 	return (0);
98 }
99 
100 static int
101 test_file_fopen(fileargs_t *fa, const char *file, const char *mode,
102     FILE **retfile)
103 {
104 	FILE *pfile;
105 
106 	pfile = fileargs_fopen(fa, file, mode);
107 	if (pfile == NULL)
108 		return (errno);
109 
110 	if (retfile != NULL) {
111 		*retfile = pfile;
112 	}
113 
114 	return (0);
115 }
116 
117 static int
118 test_file_lstat(fileargs_t *fa, const char *file)
119 {
120 	struct stat fasb, origsb;
121 	bool equals;
122 
123 	if (fileargs_lstat(fa, file, &fasb) < 0)
124 		return (errno);
125 
126 	ATF_REQUIRE(lstat(file, &origsb) == 0);
127 
128 	equals = true;
129 	equals &= (origsb.st_dev == fasb.st_dev);
130 	equals &= (origsb.st_ino == fasb.st_ino);
131 	equals &= (origsb.st_nlink == fasb.st_nlink);
132 	equals &= (origsb.st_flags == fasb.st_flags);
133 	equals &= (memcmp(&origsb.st_ctim, &fasb.st_ctim,
134 	    sizeof(fasb.st_ctim)) == 0);
135 	equals &= (memcmp(&origsb.st_birthtim, &fasb.st_birthtim,
136 	    sizeof(fasb.st_birthtim)) == 0);
137 	if (!equals) {
138 		return (EINVAL);
139 	}
140 
141 	return (0);
142 }
143 
144 static int
145 test_file_realpath_static(fileargs_t *fa, const char *file)
146 {
147 	char fapath[PATH_MAX], origpath[PATH_MAX];
148 
149 	if (fileargs_realpath(fa, file, fapath) == NULL)
150 		return (errno);
151 
152 	ATF_REQUIRE(realpath(file, origpath) != NULL);
153 
154 	if (strcmp(fapath, origpath) != 0)
155 		return (EINVAL);
156 
157 	return (0);
158 }
159 
160 static int
161 test_file_realpath_alloc(fileargs_t *fa, const char *file)
162 {
163 	char *fapath, *origpath;
164 	int serrno;
165 
166 	fapath = fileargs_realpath(fa, file, NULL);
167 	if (fapath == NULL)
168 		return (errno);
169 
170 	origpath = realpath(file, NULL);
171 	ATF_REQUIRE(origpath != NULL);
172 
173 	serrno = 0;
174 	if (strcmp(fapath, origpath) != 0)
175 		serrno = EINVAL;
176 
177 	free(fapath);
178 	free(origpath);
179 
180 	return (serrno);
181 }
182 
183 static int
184 test_file_realpath(fileargs_t *fa, const char *file)
185 {
186 	int serrno;
187 
188 	serrno = test_file_realpath_static(fa, file);
189 	if (serrno != 0)
190 		return serrno;
191 
192 	return (test_file_realpath_alloc(fa, file));
193 }
194 
195 static int
196 test_file_mode(int fd, int mode)
197 {
198 	int flags;
199 
200 	flags = fcntl(fd, F_GETFL, 0);
201 	if (flags < 0)
202 		return (errno);
203 
204 	if ((flags & O_ACCMODE) != mode)
205 		return (errno);
206 
207 	return (0);
208 }
209 
210 static bool
211 test_file_cap(int fd, cap_rights_t *rights)
212 {
213 	cap_rights_t fdrights;
214 
215 	ATF_REQUIRE(cap_rights_get(fd, &fdrights) == 0);
216 
217 	return (cap_rights_contains(&fdrights, rights));
218 }
219 
220 static int
221 test_file_write(int fd)
222 {
223 	char buf;
224 
225 	buf = 't';
226 	if (write(fd, &buf, sizeof(buf)) != sizeof(buf)) {
227 		return (errno);
228 	}
229 
230 	return (0);
231 }
232 
233 static int
234 test_file_read(int fd)
235 {
236 	char buf;
237 
238 	if (read(fd, &buf, sizeof(buf)) < 0) {
239 		return (errno);
240 	}
241 
242 	return (0);
243 }
244 
245 static int
246 test_file_fwrite(FILE *pfile)
247 {
248 	char buf;
249 
250 	buf = 't';
251 	if (fwrite(&buf, sizeof(buf), 1, pfile) != sizeof(buf))
252 		return (errno);
253 
254 	return (0);
255 }
256 
257 static int
258 test_file_fread(FILE *pfile)
259 {
260 	char buf;
261 	int ret, serrno;
262 
263 	errno = 0;
264 	ret = fread(&buf, sizeof(buf), 1, pfile);
265 	serrno = errno;
266 	if (ret < 0) {
267 		return (serrno);
268 	} else if (ret == 0 && feof(pfile) == 0) {
269 		return (serrno != 0 ? serrno : EINVAL);
270 	}
271 
272 	return (0);
273 }
274 
275 ATF_TC_WITH_CLEANUP(fileargs__open_read);
276 ATF_TC_HEAD(fileargs__open_read, tc) {}
277 ATF_TC_BODY(fileargs__open_read, tc)
278 {
279 	cap_rights_t rights, norights;
280 	fileargs_t *fa;
281 	size_t i;
282 	int fd;
283 
284 	prepare_files(MAX_FILES, true);
285 
286 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
287 	cap_rights_init(&norights, CAP_WRITE);
288 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
289 	    FA_OPEN);
290 	ATF_REQUIRE(fa != NULL);
291 
292 	for (i = 0; i < MAX_FILES; i++) {
293 		/* ALLOWED */
294 		/* We open file twice to check if we can. */
295 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
296 		ATF_REQUIRE(close(fd) == 0);
297 
298 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
299 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
300 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
301 		ATF_REQUIRE(test_file_read(fd) == 0);
302 
303 		/* DISALLOWED */
304 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
305 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
306 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
307 		ATF_REQUIRE(test_file_write(fd) == ENOTCAPABLE);
308 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
309 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
310 
311 		/* CLOSE */
312 		ATF_REQUIRE(close(fd) == 0);
313 	}
314 }
315 ATF_TC_CLEANUP(fileargs__open_read, tc)
316 {
317 	clear_files();
318 }
319 
320 ATF_TC_WITH_CLEANUP(fileargs__open_write);
321 ATF_TC_HEAD(fileargs__open_write, tc) {}
322 ATF_TC_BODY(fileargs__open_write, tc)
323 {
324 	cap_rights_t rights, norights;
325 	fileargs_t *fa;
326 	size_t i;
327 	int fd;
328 
329 	prepare_files(MAX_FILES, true);
330 
331 	cap_rights_init(&rights, CAP_WRITE | CAP_FCNTL);
332 	cap_rights_init(&norights, CAP_READ);
333 	fa = fileargs_init(MAX_FILES, files, O_WRONLY, 0, &rights,
334 	    FA_OPEN);
335 	ATF_REQUIRE(fa != NULL);
336 
337 	for (i = 0; i < MAX_FILES; i++) {
338 		/* ALLOWED */
339 		/* We open file twice to check if we can. */
340 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
341 		ATF_REQUIRE(close(fd) == 0);
342 
343 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
344 		ATF_REQUIRE(test_file_mode(fd, O_WRONLY) == 0);
345 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
346 		ATF_REQUIRE(test_file_write(fd) == 0);
347 
348 		/* DISALLOWED */
349 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
350 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
351 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
352 		ATF_REQUIRE(test_file_read(fd) == ENOTCAPABLE);
353 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
354 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
355 
356 		/* CLOSE */
357 		ATF_REQUIRE(close(fd) == 0);
358 	}
359 }
360 ATF_TC_CLEANUP(fileargs__open_write, tc)
361 {
362 	clear_files();
363 }
364 
365 ATF_TC_WITH_CLEANUP(fileargs__open_create);
366 ATF_TC_HEAD(fileargs__open_create, tc) {}
367 ATF_TC_BODY(fileargs__open_create, tc)
368 {
369 	cap_rights_t rights, norights;
370 	fileargs_t *fa;
371 	size_t i;
372 	int fd;
373 
374 	prepare_files(MAX_FILES, false);
375 
376 	cap_rights_init(&rights, CAP_WRITE | CAP_FCNTL | CAP_READ);
377 	cap_rights_init(&norights, CAP_FCHMOD);
378 	fa = fileargs_init(MAX_FILES, files, O_RDWR | O_CREAT, 666,
379 	    &rights, FA_OPEN);
380 	ATF_REQUIRE(fa != NULL);
381 
382 	for (i = 0; i < MAX_FILES; i++) {
383 		/* ALLOWED */
384 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
385 
386 		ATF_REQUIRE(test_file_mode(fd, O_RDWR) == 0);
387 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
388 		ATF_REQUIRE(test_file_write(fd) == 0);
389 		ATF_REQUIRE(test_file_read(fd) == 0);
390 
391 		/* DISALLOWED */
392 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
393 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
394 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
395 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
396 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
397 
398 		/* CLOSE */
399 		ATF_REQUIRE(close(fd) == 0);
400 	}
401 }
402 ATF_TC_CLEANUP(fileargs__open_create, tc)
403 {
404 	clear_files();
405 }
406 
407 ATF_TC_WITH_CLEANUP(fileargs__open_with_casper);
408 ATF_TC_HEAD(fileargs__open_with_casper, tc) {}
409 ATF_TC_BODY(fileargs__open_with_casper, tc)
410 {
411 	cap_channel_t *capcas;
412 	cap_rights_t rights;
413 	fileargs_t *fa;
414 	size_t i;
415 	int fd;
416 
417 	prepare_files(MAX_FILES, true);
418 
419 	capcas = cap_init();
420 	ATF_REQUIRE(capcas != NULL);
421 
422 	cap_rights_init(&rights, CAP_READ);
423 	fa = fileargs_cinit(capcas, MAX_FILES, files, O_RDONLY, 0, &rights,
424 	    FA_OPEN);
425 	ATF_REQUIRE(fa != NULL);
426 
427 	for (i = 0; i < MAX_FILES; i++) {
428 		/* ALLOWED */
429 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
430 		ATF_REQUIRE(test_file_read(fd) == 0);
431 
432 		/* CLOSE */
433 		ATF_REQUIRE(close(fd) == 0);
434 	}
435 }
436 ATF_TC_CLEANUP(fileargs__open_with_casper, tc)
437 {
438 	clear_files();
439 }
440 
441 ATF_TC_WITH_CLEANUP(fileargs__fopen_read);
442 ATF_TC_HEAD(fileargs__fopen_read, tc) {}
443 ATF_TC_BODY(fileargs__fopen_read, tc)
444 {
445 	cap_rights_t rights, norights;
446 	fileargs_t *fa;
447 	size_t i;
448 	FILE *pfile;
449 	int fd;
450 
451 	prepare_files(MAX_FILES, true);
452 
453 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
454 	cap_rights_init(&norights, CAP_WRITE);
455 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
456 	    FA_OPEN);
457 	ATF_REQUIRE(fa != NULL);
458 
459 	for (i = 0; i < MAX_FILES; i++) {
460 		/* ALLOWED */
461 		/* We fopen file twice to check if we can. */
462 		ATF_REQUIRE(test_file_fopen(fa, files[i], "r", &pfile) == 0);
463 		ATF_REQUIRE(fclose(pfile) == 0);
464 
465 		ATF_REQUIRE(test_file_fopen(fa, files[i], "r", &pfile) == 0);
466 		fd = fileno(pfile);
467 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
468 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
469 		ATF_REQUIRE(test_file_fread(pfile) == 0);
470 
471 		/* DISALLOWED */
472 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
473 		ATF_REQUIRE(test_file_fopen(fa, TEST_FILE, "r", NULL) ==
474 		    ENOTCAPABLE);
475 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
476 		ATF_REQUIRE(test_file_fwrite(pfile) == EBADF);
477 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
478 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
479 
480 		/* CLOSE */
481 		ATF_REQUIRE(fclose(pfile) == 0);
482 	}
483 }
484 ATF_TC_CLEANUP(fileargs__fopen_read, tc)
485 {
486 	clear_files();
487 }
488 
489 ATF_TC_WITH_CLEANUP(fileargs__fopen_write);
490 ATF_TC_HEAD(fileargs__fopen_write, tc) {}
491 ATF_TC_BODY(fileargs__fopen_write, tc)
492 {
493 	cap_rights_t rights, norights;
494 	fileargs_t *fa;
495 	size_t i;
496 	FILE *pfile;
497 	int fd;
498 
499 	prepare_files(MAX_FILES, true);
500 
501 	cap_rights_init(&rights, CAP_WRITE | CAP_FCNTL);
502 	cap_rights_init(&norights, CAP_READ);
503 	fa = fileargs_init(MAX_FILES, files, O_WRONLY, 0, &rights,
504 	    FA_OPEN);
505 	ATF_REQUIRE(fa != NULL);
506 
507 	for (i = 0; i < MAX_FILES; i++) {
508 		/* ALLOWED */
509 		/* We fopen file twice to check if we can. */
510 		ATF_REQUIRE(test_file_fopen(fa, files[i], "w", &pfile) == 0);
511 		ATF_REQUIRE(fclose(pfile) == 0);
512 
513 		ATF_REQUIRE(test_file_fopen(fa, files[i], "w", &pfile) == 0);
514 		fd = fileno(pfile);
515 		ATF_REQUIRE(test_file_mode(fd, O_WRONLY) == 0);
516 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
517 		ATF_REQUIRE(test_file_fwrite(pfile) == 0);
518 
519 		/* DISALLOWED */
520 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
521 		ATF_REQUIRE(test_file_fopen(fa, TEST_FILE, "w", NULL) ==
522 		    ENOTCAPABLE);
523 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
524 		ATF_REQUIRE(test_file_fread(pfile) == EBADF);
525 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
526 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
527 
528 		/* CLOSE */
529 		ATF_REQUIRE(fclose(pfile) == 0);
530 	}
531 }
532 ATF_TC_CLEANUP(fileargs__fopen_write, tc)
533 {
534 	clear_files();
535 }
536 
537 ATF_TC_WITH_CLEANUP(fileargs__fopen_create);
538 ATF_TC_HEAD(fileargs__fopen_create, tc) {}
539 ATF_TC_BODY(fileargs__fopen_create, tc)
540 {
541 	cap_rights_t rights;
542 	fileargs_t *fa;
543 	size_t i;
544 	FILE *pfile;
545 	int fd;
546 
547 	prepare_files(MAX_FILES, false);
548 
549 	cap_rights_init(&rights, CAP_READ | CAP_WRITE | CAP_FCNTL);
550 	fa = fileargs_init(MAX_FILES, files, O_RDWR | O_CREAT, 0, &rights,
551 	    FA_OPEN);
552 	ATF_REQUIRE(fa != NULL);
553 
554 	for (i = 0; i < MAX_FILES; i++) {
555 		/* ALLOWED */
556 		/* We fopen file twice to check if we can. */
557 		ATF_REQUIRE(test_file_fopen(fa, files[i], "w+", &pfile) == 0);
558 		fd = fileno(pfile);
559 		ATF_REQUIRE(test_file_mode(fd, O_RDWR) == 0);
560 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
561 		ATF_REQUIRE(test_file_fwrite(pfile) == 0);
562 		ATF_REQUIRE(test_file_fread(pfile) == 0);
563 
564 		/* DISALLOWED */
565 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
566 		ATF_REQUIRE(test_file_fopen(fa, TEST_FILE, "w+", NULL) ==
567 		    ENOTCAPABLE);
568 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
569 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
570 
571 		/* CLOSE */
572 		ATF_REQUIRE(fclose(pfile) == 0);
573 	}
574 }
575 ATF_TC_CLEANUP(fileargs__fopen_create, tc)
576 {
577 	clear_files();
578 }
579 
580 ATF_TC_WITH_CLEANUP(fileargs__lstat);
581 ATF_TC_HEAD(fileargs__lstat, tc) {}
582 ATF_TC_BODY(fileargs__lstat, tc)
583 {
584 	fileargs_t *fa;
585 	size_t i;
586 	int fd;
587 
588 	prepare_files(MAX_FILES, true);
589 
590 	fa = fileargs_init(MAX_FILES, files, 0, 0, NULL, FA_LSTAT);
591 	ATF_REQUIRE(fa != NULL);
592 
593 	for (i = 0; i < MAX_FILES; i++) {
594 		/* ALLOWED */
595 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == 0);
596 
597 		/* DISALLOWED */
598 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == ENOTCAPABLE);
599 		ATF_REQUIRE(test_file_lstat(fa, TEST_FILE) == ENOTCAPABLE);
600 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, &fd) == ENOTCAPABLE);
601 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
602 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
603 	}
604 }
605 ATF_TC_CLEANUP(fileargs__lstat, tc)
606 {
607 	clear_files();
608 }
609 
610 ATF_TC_WITH_CLEANUP(fileargs__realpath);
611 ATF_TC_HEAD(fileargs__realpath, tc) {}
612 ATF_TC_BODY(fileargs__realpath, tc)
613 {
614 	fileargs_t *fa;
615 	size_t i;
616 	int fd;
617 
618 	prepare_files(MAX_FILES, true);
619 
620 	fa = fileargs_init(MAX_FILES, files, 0, 0, NULL, FA_REALPATH);
621 	ATF_REQUIRE(fa != NULL);
622 
623 	for (i = 0; i < MAX_FILES; i++) {
624 		/* ALLOWED */
625 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == 0);
626 
627 		/* DISALLOWED */
628 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == ENOTCAPABLE);
629 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
630 		ATF_REQUIRE(test_file_lstat(fa, TEST_FILE) == ENOTCAPABLE);
631 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, &fd) == ENOTCAPABLE);
632 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
633 	}
634 }
635 ATF_TC_CLEANUP(fileargs__realpath, tc)
636 {
637 	clear_files();
638 }
639 
640 ATF_TC_WITH_CLEANUP(fileargs__open_lstat);
641 ATF_TC_HEAD(fileargs__open_lstat, tc) {}
642 ATF_TC_BODY(fileargs__open_lstat, tc)
643 {
644 	cap_rights_t rights, norights;
645 	fileargs_t *fa;
646 	size_t i;
647 	int fd;
648 
649 	prepare_files(MAX_FILES, true);
650 
651 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
652 	cap_rights_init(&norights, CAP_WRITE);
653 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
654 	    FA_OPEN | FA_LSTAT);
655 	ATF_REQUIRE(fa != NULL);
656 
657 	for (i = 0; i < MAX_FILES; i++) {
658 		/* ALLOWED */
659 		/* We open file twice to check if we can. */
660 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == 0);
661 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
662 		ATF_REQUIRE(close(fd) == 0);
663 
664 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
665 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == 0);
666 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
667 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
668 		ATF_REQUIRE(test_file_read(fd) == 0);
669 
670 		/* DISALLOWED */
671 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
672 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
673 		ATF_REQUIRE(test_file_write(fd) == ENOTCAPABLE);
674 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
675 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
676 
677 		/* CLOSE */
678 		ATF_REQUIRE(close(fd) == 0);
679 	}
680 }
681 ATF_TC_CLEANUP(fileargs__open_lstat, tc)
682 {
683 	clear_files();
684 }
685 
686 ATF_TC_WITH_CLEANUP(fileargs__open_realpath);
687 ATF_TC_HEAD(fileargs__open_realpath, tc) {}
688 ATF_TC_BODY(fileargs__open_realpath, tc)
689 {
690 	cap_rights_t rights, norights;
691 	fileargs_t *fa;
692 	size_t i;
693 	int fd;
694 
695 	prepare_files(MAX_FILES, true);
696 
697 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
698 	cap_rights_init(&norights, CAP_WRITE);
699 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
700 	    FA_OPEN | FA_REALPATH);
701 	ATF_REQUIRE(fa != NULL);
702 
703 	for (i = 0; i < MAX_FILES; i++) {
704 		/* ALLOWED */
705 		/* We open file twice to check if we can. */
706 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == 0);
707 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
708 		ATF_REQUIRE(close(fd) == 0);
709 
710 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
711 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == 0);
712 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
713 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
714 		ATF_REQUIRE(test_file_read(fd) == 0);
715 
716 		/* DISALLOWED */
717 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
718 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
719 		ATF_REQUIRE(test_file_write(fd) == ENOTCAPABLE);
720 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
721 
722 		/* CLOSE */
723 		ATF_REQUIRE(close(fd) == 0);
724 	}
725 }
726 ATF_TC_CLEANUP(fileargs__open_realpath, tc)
727 {
728 	clear_files();
729 }
730 
731 ATF_TP_ADD_TCS(tp)
732 {
733 
734 	ATF_TP_ADD_TC(tp, fileargs__open_create);
735 	ATF_TP_ADD_TC(tp, fileargs__open_read);
736 	ATF_TP_ADD_TC(tp, fileargs__open_write);
737 	ATF_TP_ADD_TC(tp, fileargs__open_with_casper);
738 
739 	ATF_TP_ADD_TC(tp, fileargs__fopen_create);
740 	ATF_TP_ADD_TC(tp, fileargs__fopen_read);
741 	ATF_TP_ADD_TC(tp, fileargs__fopen_write);
742 
743 	ATF_TP_ADD_TC(tp, fileargs__lstat);
744 
745 	ATF_TP_ADD_TC(tp, fileargs__realpath);
746 
747 	ATF_TP_ADD_TC(tp, fileargs__open_lstat);
748 	ATF_TP_ADD_TC(tp, fileargs__open_realpath);
749 
750 	return (atf_no_error());
751 }
752