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