1/*-
2 * Copyright 2018 Aniket Pandey
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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD$
26 */
27
28#include <sys/types.h>
29#include <sys/stat.h>
30
31#include <atf-c.h>
32#include <fcntl.h>
33#include <stdlib.h>
34#include <unistd.h>
35
36#include "utils.h"
37
38static struct pollfd fds[1];
39static mode_t mode = 0777;
40static int filedesc;
41static dev_t dev =  0;
42static const char *auclass = "fc";
43static const char *path = "fileforaudit";
44static const char *successreg = "fileforaudit.*return,success";
45static const char *failurereg = "fileforaudit.*return,failure";
46
47
48ATF_TC_WITH_CLEANUP(mkdir_success);
49ATF_TC_HEAD(mkdir_success, tc)
50{
51	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
52					"mkdir(2) call");
53}
54
55ATF_TC_BODY(mkdir_success, tc)
56{
57	FILE *pipefd = setup(fds, auclass);
58	ATF_REQUIRE_EQ(0, mkdir(path, mode));
59	check_audit(fds, successreg, pipefd);
60}
61
62ATF_TC_CLEANUP(mkdir_success, tc)
63{
64	cleanup();
65}
66
67
68ATF_TC_WITH_CLEANUP(mkdir_failure);
69ATF_TC_HEAD(mkdir_failure, tc)
70{
71	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
72					"mkdir(2) call");
73}
74
75ATF_TC_BODY(mkdir_failure, tc)
76{
77	ATF_REQUIRE_EQ(0, mkdir(path, mode));
78	FILE *pipefd = setup(fds, auclass);
79	/* Failure reason: directory already exists */
80	ATF_REQUIRE_EQ(-1, mkdir(path, mode));
81	check_audit(fds, failurereg, pipefd);
82}
83
84ATF_TC_CLEANUP(mkdir_failure, tc)
85{
86	cleanup();
87}
88
89
90ATF_TC_WITH_CLEANUP(mkdirat_success);
91ATF_TC_HEAD(mkdirat_success, tc)
92{
93	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
94					"mkdirat(2) call");
95}
96
97ATF_TC_BODY(mkdirat_success, tc)
98{
99	FILE *pipefd = setup(fds, auclass);
100	ATF_REQUIRE_EQ(0, mkdirat(AT_FDCWD, path, mode));
101	check_audit(fds, successreg, pipefd);
102}
103
104ATF_TC_CLEANUP(mkdirat_success, tc)
105{
106	cleanup();
107}
108
109
110ATF_TC_WITH_CLEANUP(mkdirat_failure);
111ATF_TC_HEAD(mkdirat_failure, tc)
112{
113	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
114					"mkdirat(2) call");
115}
116
117ATF_TC_BODY(mkdirat_failure, tc)
118{
119	ATF_REQUIRE_EQ(0, mkdirat(AT_FDCWD, path, mode));
120	FILE *pipefd = setup(fds, auclass);
121	/* Failure reason: directory already exists */
122	ATF_REQUIRE_EQ(-1, mkdirat(AT_FDCWD, path, mode));
123	check_audit(fds, failurereg, pipefd);
124}
125
126ATF_TC_CLEANUP(mkdirat_failure, tc)
127{
128	cleanup();
129}
130
131
132ATF_TC_WITH_CLEANUP(mkfifo_success);
133ATF_TC_HEAD(mkfifo_success, tc)
134{
135	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
136					"mkfifo(2) call");
137}
138
139ATF_TC_BODY(mkfifo_success, tc)
140{
141	FILE *pipefd = setup(fds, auclass);
142	ATF_REQUIRE_EQ(0, mkfifo(path, mode));
143	check_audit(fds, successreg, pipefd);
144}
145
146ATF_TC_CLEANUP(mkfifo_success, tc)
147{
148	cleanup();
149}
150
151
152ATF_TC_WITH_CLEANUP(mkfifo_failure);
153ATF_TC_HEAD(mkfifo_failure, tc)
154{
155	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
156					"mkfifo(2) call");
157}
158
159ATF_TC_BODY(mkfifo_failure, tc)
160{
161	ATF_REQUIRE_EQ(0, mkfifo(path, mode));
162	FILE *pipefd = setup(fds, auclass);
163	/* Failure reason: FIFO already exists */
164	ATF_REQUIRE_EQ(-1, mkfifo(path, mode));
165	check_audit(fds, failurereg, pipefd);
166}
167
168ATF_TC_CLEANUP(mkfifo_failure, tc)
169{
170	cleanup();
171}
172
173
174ATF_TC_WITH_CLEANUP(mkfifoat_success);
175ATF_TC_HEAD(mkfifoat_success, tc)
176{
177	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
178					"mkfifoat(2) call");
179}
180
181ATF_TC_BODY(mkfifoat_success, tc)
182{
183	FILE *pipefd = setup(fds, auclass);
184	ATF_REQUIRE_EQ(0, mkfifoat(AT_FDCWD, path, mode));
185	check_audit(fds, successreg, pipefd);
186}
187
188ATF_TC_CLEANUP(mkfifoat_success, tc)
189{
190	cleanup();
191}
192
193
194ATF_TC_WITH_CLEANUP(mkfifoat_failure);
195ATF_TC_HEAD(mkfifoat_failure, tc)
196{
197	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
198					"mkfifoat(2) call");
199}
200
201ATF_TC_BODY(mkfifoat_failure, tc)
202{
203	ATF_REQUIRE_EQ(0, mkfifoat(AT_FDCWD, path, mode));
204	FILE *pipefd = setup(fds, auclass);
205	/* Failure reason: FIFO already exists */
206	ATF_REQUIRE_EQ(-1, mkfifoat(AT_FDCWD, path, mode));
207	check_audit(fds, failurereg, pipefd);
208}
209
210ATF_TC_CLEANUP(mkfifoat_failure, tc)
211{
212	cleanup();
213}
214
215
216ATF_TC_WITH_CLEANUP(mknod_success);
217ATF_TC_HEAD(mknod_success, tc)
218{
219	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
220					"mknod(2) call");
221}
222
223ATF_TC_BODY(mknod_success, tc)
224{
225	FILE *pipefd = setup(fds, auclass);
226	ATF_REQUIRE_EQ(0, mknod(path, S_IFIFO | S_IRWXO, dev));
227	check_audit(fds, successreg, pipefd);
228}
229
230ATF_TC_CLEANUP(mknod_success, tc)
231{
232	cleanup();
233}
234
235
236ATF_TC_WITH_CLEANUP(mknod_failure);
237ATF_TC_HEAD(mknod_failure, tc)
238{
239	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
240					"mknod(2) call");
241}
242
243ATF_TC_BODY(mknod_failure, tc)
244{
245	ATF_REQUIRE_EQ(0, mknod(path, S_IFIFO | S_IRWXO, dev));
246	FILE *pipefd = setup(fds, auclass);
247	/* Failure reason: FIFO node already exists */
248	ATF_REQUIRE_EQ(-1, mknod(path, S_IFIFO | S_IRWXO, dev));
249	check_audit(fds, failurereg, pipefd);
250}
251
252ATF_TC_CLEANUP(mknod_failure, tc)
253{
254	cleanup();
255}
256
257
258ATF_TC_WITH_CLEANUP(mknodat_success);
259ATF_TC_HEAD(mknodat_success, tc)
260{
261	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
262					"mknodat(2) call");
263}
264
265ATF_TC_BODY(mknodat_success, tc)
266{
267	FILE *pipefd = setup(fds, auclass);
268	ATF_REQUIRE_EQ(0, mknodat(AT_FDCWD, path, S_IFIFO | S_IRWXO, dev));
269	check_audit(fds, successreg, pipefd);
270}
271
272ATF_TC_CLEANUP(mknodat_success, tc)
273{
274	cleanup();
275}
276
277
278ATF_TC_WITH_CLEANUP(mknodat_failure);
279ATF_TC_HEAD(mknodat_failure, tc)
280{
281	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
282					"mknodat(2) call");
283}
284
285ATF_TC_BODY(mknodat_failure, tc)
286{
287	ATF_REQUIRE_EQ(0, mknodat(AT_FDCWD, path, S_IFIFO | S_IRWXO, dev));
288	FILE *pipefd = setup(fds, auclass);
289	/* Failure reason: FIFO node already exists */
290	ATF_REQUIRE_EQ(-1, mknodat(AT_FDCWD, path, S_IFIFO | S_IRWXO, dev));
291	check_audit(fds, failurereg, pipefd);
292}
293
294ATF_TC_CLEANUP(mknodat_failure, tc)
295{
296	cleanup();
297}
298
299
300ATF_TC_WITH_CLEANUP(rename_success);
301ATF_TC_HEAD(rename_success, tc)
302{
303	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
304					"rename(2) call");
305}
306
307ATF_TC_BODY(rename_success, tc)
308{
309	ATF_REQUIRE((filedesc = open(path, O_CREAT, mode)) != -1);
310	FILE *pipefd = setup(fds, auclass);
311	ATF_REQUIRE_EQ(0, rename(path, "renamed"));
312	check_audit(fds, successreg, pipefd);
313	close(filedesc);
314}
315
316ATF_TC_CLEANUP(rename_success, tc)
317{
318	cleanup();
319}
320
321
322ATF_TC_WITH_CLEANUP(rename_failure);
323ATF_TC_HEAD(rename_failure, tc)
324{
325	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
326					"rename(2) call");
327}
328
329ATF_TC_BODY(rename_failure, tc)
330{
331	FILE *pipefd = setup(fds, auclass);
332	/* Failure reason: file does not exist */
333	ATF_REQUIRE_EQ(-1, rename(path, "renamed"));
334	check_audit(fds, failurereg, pipefd);
335}
336
337ATF_TC_CLEANUP(rename_failure, tc)
338{
339	cleanup();
340}
341
342
343ATF_TC_WITH_CLEANUP(renameat_success);
344ATF_TC_HEAD(renameat_success, tc)
345{
346	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
347					"renameat(2) call");
348}
349
350ATF_TC_BODY(renameat_success, tc)
351{
352	ATF_REQUIRE((filedesc = open(path, O_CREAT, mode)) != -1);
353	FILE *pipefd = setup(fds, auclass);
354	ATF_REQUIRE_EQ(0, renameat(AT_FDCWD, path, AT_FDCWD, "renamed"));
355	check_audit(fds, successreg, pipefd);
356	close(filedesc);
357}
358
359ATF_TC_CLEANUP(renameat_success, tc)
360{
361	cleanup();
362}
363
364
365ATF_TC_WITH_CLEANUP(renameat_failure);
366ATF_TC_HEAD(renameat_failure, tc)
367{
368	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
369					"renameat(2) call");
370}
371
372ATF_TC_BODY(renameat_failure, tc)
373{
374	FILE *pipefd = setup(fds, auclass);
375	/* Failure reason: file does not exist */
376	ATF_REQUIRE_EQ(-1, renameat(AT_FDCWD, path, AT_FDCWD, "renamed"));
377	check_audit(fds, failurereg, pipefd);
378}
379
380ATF_TC_CLEANUP(renameat_failure, tc)
381{
382	cleanup();
383}
384
385
386ATF_TC_WITH_CLEANUP(link_success);
387ATF_TC_HEAD(link_success, tc)
388{
389	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
390					"link(2) call");
391}
392
393ATF_TC_BODY(link_success, tc)
394{
395	ATF_REQUIRE((filedesc = open(path, O_CREAT, mode)) != -1);
396	FILE *pipefd = setup(fds, auclass);
397	ATF_REQUIRE_EQ(0, link(path, "hardlink"));
398	check_audit(fds, successreg, pipefd);
399	close(filedesc);
400}
401
402ATF_TC_CLEANUP(link_success, tc)
403{
404	cleanup();
405}
406
407
408ATF_TC_WITH_CLEANUP(link_failure);
409ATF_TC_HEAD(link_failure, tc)
410{
411	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
412					"link(2) call");
413}
414
415ATF_TC_BODY(link_failure, tc)
416{
417	FILE *pipefd = setup(fds, auclass);
418	/* Failure reason: file does not exist */
419	ATF_REQUIRE_EQ(-1, link(path, "hardlink"));
420	check_audit(fds, failurereg, pipefd);
421}
422
423ATF_TC_CLEANUP(link_failure, tc)
424{
425	cleanup();
426}
427
428
429ATF_TC_WITH_CLEANUP(linkat_success);
430ATF_TC_HEAD(linkat_success, tc)
431{
432	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
433					"linkat(2) call");
434}
435
436ATF_TC_BODY(linkat_success, tc)
437{
438	ATF_REQUIRE((filedesc = open(path, O_CREAT, mode)) != -1);
439	FILE *pipefd = setup(fds, auclass);
440	ATF_REQUIRE_EQ(0, linkat(AT_FDCWD, path, AT_FDCWD, "hardlink", 0));
441	check_audit(fds, successreg, pipefd);
442	close(filedesc);
443}
444
445ATF_TC_CLEANUP(linkat_success, tc)
446{
447	cleanup();
448}
449
450
451ATF_TC_WITH_CLEANUP(linkat_failure);
452ATF_TC_HEAD(linkat_failure, tc)
453{
454	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
455					"linkat(2) call");
456}
457
458ATF_TC_BODY(linkat_failure, tc)
459{
460	FILE *pipefd = setup(fds, auclass);
461	/* Failure reason: file does not exist */
462	ATF_REQUIRE_EQ(-1, linkat(AT_FDCWD, path, AT_FDCWD, "hardlink", 0));
463	check_audit(fds, failurereg, pipefd);
464}
465
466ATF_TC_CLEANUP(linkat_failure, tc)
467{
468	cleanup();
469}
470
471
472ATF_TC_WITH_CLEANUP(symlink_success);
473ATF_TC_HEAD(symlink_success, tc)
474{
475	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
476					"symlink(2) call");
477}
478
479ATF_TC_BODY(symlink_success, tc)
480{
481	FILE *pipefd = setup(fds, auclass);
482	ATF_REQUIRE_EQ(0, symlink(path, "symlink"));
483	check_audit(fds, successreg, pipefd);
484}
485
486ATF_TC_CLEANUP(symlink_success, tc)
487{
488	cleanup();
489}
490
491
492ATF_TC_WITH_CLEANUP(symlink_failure);
493ATF_TC_HEAD(symlink_failure, tc)
494{
495	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
496					"symlink(2) call");
497}
498
499ATF_TC_BODY(symlink_failure, tc)
500{
501	ATF_REQUIRE_EQ(0, symlink(path, "symlink"));
502	FILE *pipefd = setup(fds, auclass);
503	/* Failure reason: symbolic link already exists */
504	ATF_REQUIRE_EQ(-1, symlink(path, "symlink"));
505	check_audit(fds, failurereg, pipefd);
506}
507
508ATF_TC_CLEANUP(symlink_failure, tc)
509{
510	cleanup();
511}
512
513
514ATF_TC_WITH_CLEANUP(symlinkat_success);
515ATF_TC_HEAD(symlinkat_success, tc)
516{
517	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
518					"symlinkat(2) call");
519}
520
521ATF_TC_BODY(symlinkat_success, tc)
522{
523	FILE *pipefd = setup(fds, auclass);
524	ATF_REQUIRE_EQ(0, symlinkat(path, AT_FDCWD, "symlink"));
525	check_audit(fds, successreg, pipefd);
526}
527
528ATF_TC_CLEANUP(symlinkat_success, tc)
529{
530	cleanup();
531}
532
533
534ATF_TC_WITH_CLEANUP(symlinkat_failure);
535ATF_TC_HEAD(symlinkat_failure, tc)
536{
537	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
538					"symlinkat(2) call");
539}
540
541ATF_TC_BODY(symlinkat_failure, tc)
542{
543	ATF_REQUIRE_EQ(0, symlinkat(path, AT_FDCWD, "symlink"));
544	FILE *pipefd = setup(fds, auclass);
545	/* Failure reason: symbolic link already exists */
546	ATF_REQUIRE_EQ(-1, symlinkat(path, AT_FDCWD, "symlink"));
547	check_audit(fds, failurereg, pipefd);
548}
549
550ATF_TC_CLEANUP(symlinkat_failure, tc)
551{
552	cleanup();
553}
554
555
556ATF_TP_ADD_TCS(tp)
557{
558	ATF_TP_ADD_TC(tp, mkdir_success);
559	ATF_TP_ADD_TC(tp, mkdir_failure);
560	ATF_TP_ADD_TC(tp, mkdirat_success);
561	ATF_TP_ADD_TC(tp, mkdirat_failure);
562
563	ATF_TP_ADD_TC(tp, mkfifo_success);
564	ATF_TP_ADD_TC(tp, mkfifo_failure);
565	ATF_TP_ADD_TC(tp, mkfifoat_success);
566	ATF_TP_ADD_TC(tp, mkfifoat_failure);
567
568	ATF_TP_ADD_TC(tp, mknod_success);
569	ATF_TP_ADD_TC(tp, mknod_failure);
570	ATF_TP_ADD_TC(tp, mknodat_success);
571	ATF_TP_ADD_TC(tp, mknodat_failure);
572
573	ATF_TP_ADD_TC(tp, rename_success);
574	ATF_TP_ADD_TC(tp, rename_failure);
575	ATF_TP_ADD_TC(tp, renameat_success);
576	ATF_TP_ADD_TC(tp, renameat_failure);
577
578	ATF_TP_ADD_TC(tp, link_success);
579	ATF_TP_ADD_TC(tp, link_failure);
580	ATF_TP_ADD_TC(tp, linkat_success);
581	ATF_TP_ADD_TC(tp, linkat_failure);
582
583	ATF_TP_ADD_TC(tp, symlink_success);
584	ATF_TP_ADD_TC(tp, symlink_failure);
585	ATF_TP_ADD_TC(tp, symlinkat_success);
586	ATF_TP_ADD_TC(tp, symlinkat_failure);
587
588	return (atf_no_error());
589}
590