1/*-
2 * Copyright (c) 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/socket.h>
28#include <sys/stat.h>
29#include <sys/uio.h>
30#include <sys/un.h>
31
32#include <atf-c.h>
33#include <fcntl.h>
34#include <stdarg.h>
35#include <unistd.h>
36
37#include "utils.h"
38
39#define MAX_DATA 128
40#define SERVER_PATH "server"
41
42static pid_t pid;
43static mode_t mode = 0777;
44static int sockfd, sockfd2, connectfd;
45static ssize_t data_bytes;
46static socklen_t len = sizeof(struct sockaddr_un);
47static struct iovec io1, io2;
48static struct pollfd fds[1];
49static struct sockaddr_un server;
50static struct msghdr sendbuf, recvbuf;
51static char extregex[MAX_DATA];
52static char data[MAX_DATA];
53static char msgbuff[MAX_DATA] = "This message does not exist";
54static const char *auclass = "nt";
55static const char *path = "fileforaudit";
56static const char *nosupregex = "return,failure : Address family "
57				"not supported by protocol family";
58static const char *invalregex = "return,failure : Bad file descriptor";
59
60/*
61 * Initialize iovec structure to be used as a field of struct msghdr
62 */
63static void
64init_iov(struct iovec *io, char msgbuf[], int datalen)
65{
66	io->iov_base = msgbuf;
67	io->iov_len = datalen;
68}
69
70/*
71 * Initialize msghdr structure for communication via datagram sockets
72 */
73static void
74init_msghdr(struct msghdr *hdrbuf, struct iovec *io, struct sockaddr_un *addr)
75{
76	socklen_t length;
77
78	bzero(hdrbuf, sizeof(*hdrbuf));
79	length = (socklen_t)sizeof(struct sockaddr_un);
80	hdrbuf->msg_name = addr;
81	hdrbuf->msg_namelen = length;
82	hdrbuf->msg_iov = io;
83	hdrbuf->msg_iovlen = 1;
84}
85
86/*
87 * Variadic function to close socket descriptors
88 */
89static void
90close_sockets(int count, ...)
91{
92	int sockd;
93	va_list socklist;
94	va_start(socklist, count);
95	for (sockd = 0; sockd < count; sockd++) {
96		close(va_arg(socklist, int));
97	}
98	va_end(socklist);
99}
100
101/*
102 * Assign local filesystem address to a Unix domain socket
103 */
104static void
105assign_address(struct sockaddr_un *serveraddr)
106{
107	memset(serveraddr, 0, sizeof(*serveraddr));
108	serveraddr->sun_family = AF_UNIX;
109	strcpy(serveraddr->sun_path, SERVER_PATH);
110}
111
112
113ATF_TC_WITH_CLEANUP(socket_success);
114ATF_TC_HEAD(socket_success, tc)
115{
116	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
117					"socket(2) call");
118}
119
120ATF_TC_BODY(socket_success, tc)
121{
122	FILE *pipefd = setup(fds, auclass);
123	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
124	/* Check the presence of sockfd in audit record */
125	snprintf(extregex, sizeof(extregex), "socket.*ret.*success,%d", sockfd);
126	check_audit(fds, extregex, pipefd);
127	close(sockfd);
128}
129
130ATF_TC_CLEANUP(socket_success, tc)
131{
132	cleanup();
133}
134
135
136ATF_TC_WITH_CLEANUP(socket_failure);
137ATF_TC_HEAD(socket_failure, tc)
138{
139	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
140					"socket(2) call");
141}
142
143ATF_TC_BODY(socket_failure, tc)
144{
145	snprintf(extregex, sizeof(extregex), "socket.*%s", nosupregex);
146	FILE *pipefd = setup(fds, auclass);
147	/* Failure reason: Unsupported value of 'domain' argument: 0 */
148	ATF_REQUIRE_EQ(-1, socket(0, SOCK_STREAM, 0));
149	check_audit(fds, extregex, pipefd);
150}
151
152ATF_TC_CLEANUP(socket_failure, tc)
153{
154	cleanup();
155}
156
157
158ATF_TC_WITH_CLEANUP(socketpair_success);
159ATF_TC_HEAD(socketpair_success, tc)
160{
161	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
162					"socketpair(2) call");
163}
164
165ATF_TC_BODY(socketpair_success, tc)
166{
167	int sv[2];
168	FILE *pipefd = setup(fds, auclass);
169	ATF_REQUIRE_EQ(0, socketpair(PF_UNIX, SOCK_STREAM, 0, sv));
170
171	/* Check for 0x0 (argument 3: default protocol) in the audit record */
172	snprintf(extregex, sizeof(extregex), "socketpair.*0x0.*return,success");
173	check_audit(fds, extregex, pipefd);
174	close_sockets(2, sv[0], sv[1]);
175}
176
177ATF_TC_CLEANUP(socketpair_success, tc)
178{
179	cleanup();
180}
181
182
183ATF_TC_WITH_CLEANUP(socketpair_failure);
184ATF_TC_HEAD(socketpair_failure, tc)
185{
186	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
187					"socketpair(2) call");
188}
189
190ATF_TC_BODY(socketpair_failure, tc)
191{
192	snprintf(extregex, sizeof(extregex), "socketpair.*%s", nosupregex);
193	FILE *pipefd = setup(fds, auclass);
194	/* Failure reason: Unsupported value of 'domain' argument: 0 */
195	ATF_REQUIRE_EQ(-1, socketpair(0, SOCK_STREAM, 0, NULL));
196	check_audit(fds, extregex, pipefd);
197}
198
199ATF_TC_CLEANUP(socketpair_failure, tc)
200{
201	cleanup();
202}
203
204
205ATF_TC_WITH_CLEANUP(setsockopt_success);
206ATF_TC_HEAD(setsockopt_success, tc)
207{
208	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
209					"setsockopt(2) call");
210}
211
212ATF_TC_BODY(setsockopt_success, tc)
213{
214	int tr = 1;
215	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
216	/* Check the presence of sockfd in audit record */
217	snprintf(extregex, sizeof(extregex),
218			"setsockopt.*0x%x.*return,success", sockfd);
219
220	FILE *pipefd = setup(fds, auclass);
221	ATF_REQUIRE_EQ(0, setsockopt(sockfd, SOL_SOCKET,
222		SO_REUSEADDR, &tr, sizeof(int)));
223	check_audit(fds, extregex, pipefd);
224	close(sockfd);
225}
226
227ATF_TC_CLEANUP(setsockopt_success, tc)
228{
229	cleanup();
230}
231
232
233ATF_TC_WITH_CLEANUP(setsockopt_failure);
234ATF_TC_HEAD(setsockopt_failure, tc)
235{
236	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
237					"setsockopt(2) call");
238}
239
240ATF_TC_BODY(setsockopt_failure, tc)
241{
242	snprintf(extregex, sizeof(extregex), "setsockopt.*%s", invalregex);
243	FILE *pipefd = setup(fds, auclass);
244	/* Failure reason: Invalid socket descriptor */
245	ATF_REQUIRE_EQ(-1, setsockopt(-1, SOL_SOCKET, 0, NULL, 0));
246	check_audit(fds, extregex, pipefd);
247}
248
249ATF_TC_CLEANUP(setsockopt_failure, tc)
250{
251	cleanup();
252}
253
254
255ATF_TC_WITH_CLEANUP(bind_success);
256ATF_TC_HEAD(bind_success, tc)
257{
258	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
259					"bind(2) call");
260}
261
262ATF_TC_BODY(bind_success, tc)
263{
264	assign_address(&server);
265	/* Preliminary socket setup */
266	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
267	/* Check the presence of AF_UNIX address path in audit record */
268	snprintf(extregex, sizeof(extregex),
269		"bind.*unix.*%s.*return,success", SERVER_PATH);
270
271	FILE *pipefd = setup(fds, auclass);
272	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
273	check_audit(fds, extregex, pipefd);
274	close(sockfd);
275}
276
277ATF_TC_CLEANUP(bind_success, tc)
278{
279	cleanup();
280}
281
282
283ATF_TC_WITH_CLEANUP(bind_failure);
284ATF_TC_HEAD(bind_failure, tc)
285{
286	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
287					"bind(2) call");
288}
289
290ATF_TC_BODY(bind_failure, tc)
291{
292	assign_address(&server);
293	/* Check the presence of AF_UNIX path in audit record */
294	snprintf(extregex, sizeof(extregex),
295			"bind.*%s.*return,failure", SERVER_PATH);
296
297	FILE *pipefd = setup(fds, auclass);
298	/* Failure reason: Invalid socket descriptor */
299	ATF_REQUIRE_EQ(-1, bind(0, (struct sockaddr *)&server, len));
300	check_audit(fds, extregex, pipefd);
301}
302
303ATF_TC_CLEANUP(bind_failure, tc)
304{
305	cleanup();
306}
307
308
309ATF_TC_WITH_CLEANUP(bindat_success);
310ATF_TC_HEAD(bindat_success, tc)
311{
312	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
313					"bindat(2) call");
314}
315
316ATF_TC_BODY(bindat_success, tc)
317{
318	assign_address(&server);
319	/* Preliminary socket setup */
320	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
321	/* Check the presence of socket descriptor in audit record */
322	snprintf(extregex, sizeof(extregex),
323			"bindat.*0x%x.*return,success", sockfd);
324
325	FILE *pipefd = setup(fds, auclass);
326	ATF_REQUIRE_EQ(0, bindat(AT_FDCWD, sockfd,
327			(struct sockaddr *)&server, len));
328	check_audit(fds, extregex, pipefd);
329	close(sockfd);
330}
331
332ATF_TC_CLEANUP(bindat_success, tc)
333{
334	cleanup();
335}
336
337
338ATF_TC_WITH_CLEANUP(bindat_failure);
339ATF_TC_HEAD(bindat_failure, tc)
340{
341	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
342					"bindat(2) call");
343}
344
345ATF_TC_BODY(bindat_failure, tc)
346{
347	assign_address(&server);
348	snprintf(extregex, sizeof(extregex), "bindat.*%s", invalregex);
349
350	FILE *pipefd = setup(fds, auclass);
351	/* Failure reason: Invalid socket descriptor */
352	ATF_REQUIRE_EQ(-1, bindat(AT_FDCWD, -1,
353			(struct sockaddr *)&server, len));
354	check_audit(fds, extregex, pipefd);
355}
356
357ATF_TC_CLEANUP(bindat_failure, tc)
358{
359	cleanup();
360}
361
362
363ATF_TC_WITH_CLEANUP(listen_success);
364ATF_TC_HEAD(listen_success, tc)
365{
366	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
367					"listen(2) call");
368}
369
370ATF_TC_BODY(listen_success, tc)
371{
372	assign_address(&server);
373	/* Preliminary socket setup */
374	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
375	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
376	/* Check the presence of socket descriptor in the audit record */
377	snprintf(extregex, sizeof(extregex),
378			"listen.*0x%x.*return,success", sockfd);
379
380	FILE *pipefd = setup(fds, auclass);
381	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
382	check_audit(fds, extregex, pipefd);
383	close(sockfd);
384}
385
386ATF_TC_CLEANUP(listen_success, tc)
387{
388	cleanup();
389}
390
391
392ATF_TC_WITH_CLEANUP(listen_failure);
393ATF_TC_HEAD(listen_failure, tc)
394{
395	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
396					"listen(2) call");
397}
398
399ATF_TC_BODY(listen_failure, tc)
400{
401	snprintf(extregex, sizeof(extregex), "listen.*%s", invalregex);
402	FILE *pipefd = setup(fds, auclass);
403	/* Failure reason: Invalid socket descriptor */
404	ATF_REQUIRE_EQ(-1, listen(-1, 1));
405	check_audit(fds, extregex, pipefd);
406}
407
408ATF_TC_CLEANUP(listen_failure, tc)
409{
410	cleanup();
411}
412
413
414ATF_TC_WITH_CLEANUP(connect_success);
415ATF_TC_HEAD(connect_success, tc)
416{
417	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
418					"connect(2) call");
419}
420
421ATF_TC_BODY(connect_success, tc)
422{
423	assign_address(&server);
424	/* Setup a server socket and bind to the specified address */
425	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
426	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
427	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
428
429	/* Set up "blocking" client socket */
430	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
431
432	/* Audit record must contain AF_UNIX address path & sockfd2 */
433	snprintf(extregex, sizeof(extregex),
434			"connect.*0x%x.*%s.*success", sockfd2, SERVER_PATH);
435
436	FILE *pipefd = setup(fds, auclass);
437	ATF_REQUIRE_EQ(0, connect(sockfd2, (struct sockaddr *)&server, len));
438	check_audit(fds, extregex, pipefd);
439
440	/* Close all socket descriptors */
441	close_sockets(2, sockfd, sockfd2);
442}
443
444ATF_TC_CLEANUP(connect_success, tc)
445{
446	cleanup();
447}
448
449
450ATF_TC_WITH_CLEANUP(connect_failure);
451ATF_TC_HEAD(connect_failure, tc)
452{
453	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
454					"connect(2) call");
455}
456
457ATF_TC_BODY(connect_failure, tc)
458{
459	assign_address(&server);
460	/* Audit record must contain AF_UNIX address path */
461	snprintf(extregex, sizeof(extregex),
462			"connect.*%s.*return,failure", SERVER_PATH);
463
464	FILE *pipefd = setup(fds, auclass);
465	/* Failure reason: Invalid socket descriptor */
466	ATF_REQUIRE_EQ(-1, connect(-1, (struct sockaddr *)&server, len));
467	check_audit(fds, extregex, pipefd);
468}
469
470ATF_TC_CLEANUP(connect_failure, tc)
471{
472	cleanup();
473}
474
475
476ATF_TC_WITH_CLEANUP(connectat_success);
477ATF_TC_HEAD(connectat_success, tc)
478{
479	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
480					"connectat(2) call");
481}
482
483ATF_TC_BODY(connectat_success, tc)
484{
485	assign_address(&server);
486	/* Setup a server socket and bind to the specified address */
487	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
488	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
489	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
490
491	/* Set up "blocking" client socket */
492	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
493
494	/* Audit record must contain sockfd2 */
495	snprintf(extregex, sizeof(extregex),
496			"connectat.*0x%x.*return,success", sockfd2);
497
498	FILE *pipefd = setup(fds, auclass);
499	ATF_REQUIRE_EQ(0, connectat(AT_FDCWD, sockfd2,
500			(struct sockaddr *)&server, len));
501	check_audit(fds, extregex, pipefd);
502
503	/* Close all socket descriptors */
504	close_sockets(2, sockfd, sockfd2);
505}
506
507ATF_TC_CLEANUP(connectat_success, tc)
508{
509	cleanup();
510}
511
512
513ATF_TC_WITH_CLEANUP(connectat_failure);
514ATF_TC_HEAD(connectat_failure, tc)
515{
516	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
517					"connectat(2) call");
518}
519
520ATF_TC_BODY(connectat_failure, tc)
521{
522	assign_address(&server);
523	snprintf(extregex, sizeof(extregex), "connectat.*%s", invalregex);
524
525	FILE *pipefd = setup(fds, auclass);
526	/* Failure reason: Invalid socket descriptor */
527	ATF_REQUIRE_EQ(-1, connectat(AT_FDCWD, -1,
528			(struct sockaddr *)&server, len));
529	check_audit(fds, extregex, pipefd);
530}
531
532ATF_TC_CLEANUP(connectat_failure, tc)
533{
534	cleanup();
535}
536
537
538ATF_TC_WITH_CLEANUP(accept_success);
539ATF_TC_HEAD(accept_success, tc)
540{
541	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
542					"accept(2) call");
543}
544
545ATF_TC_BODY(accept_success, tc)
546{
547	assign_address(&server);
548	/* Setup a server socket and bind to the specified address */
549	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
550	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
551	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
552
553	/* Set up "blocking" client socket */
554	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
555	ATF_REQUIRE_EQ(0, connect(sockfd2, (struct sockaddr *)&server, len));
556
557	FILE *pipefd = setup(fds, auclass);
558	ATF_REQUIRE((connectfd = accept(sockfd, NULL, &len)) != -1);
559
560	/* Audit record must contain connectfd & sockfd */
561	snprintf(extregex, sizeof(extregex),
562			"accept.*0x%x.*return,success,%d", sockfd, connectfd);
563	check_audit(fds, extregex, pipefd);
564
565	/* Close all socket descriptors */
566	close_sockets(3, sockfd, sockfd2, connectfd);
567}
568
569ATF_TC_CLEANUP(accept_success, tc)
570{
571	cleanup();
572}
573
574
575ATF_TC_WITH_CLEANUP(accept_failure);
576ATF_TC_HEAD(accept_failure, tc)
577{
578	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
579					"accept(2) call");
580}
581
582ATF_TC_BODY(accept_failure, tc)
583{
584	snprintf(extregex, sizeof(extregex), "accept.*%s", invalregex);
585	FILE *pipefd = setup(fds, auclass);
586	/* Failure reason: Invalid socket descriptor */
587	ATF_REQUIRE_EQ(-1, accept(-1, NULL, NULL));
588	check_audit(fds, extregex, pipefd);
589}
590
591ATF_TC_CLEANUP(accept_failure, tc)
592{
593	cleanup();
594}
595
596
597ATF_TC_WITH_CLEANUP(send_success);
598ATF_TC_HEAD(send_success, tc)
599{
600	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
601					"send(2) call");
602}
603
604ATF_TC_BODY(send_success, tc)
605{
606	assign_address(&server);
607	/* Setup a server socket and bind to the specified address */
608	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
609	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
610	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
611
612	/* Set up "blocking" client and connect with non-blocking server */
613	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
614	ATF_REQUIRE_EQ(0, connect(sockfd2, (struct sockaddr *)&server, len));
615	ATF_REQUIRE((connectfd = accept(sockfd, NULL, &len)) != -1);
616
617	/* Send a sample message to the connected socket */
618	FILE *pipefd = setup(fds, auclass);
619	ATF_REQUIRE((data_bytes =
620		send(sockfd2, msgbuff, strlen(msgbuff), 0)) != -1);
621
622	/* Audit record must contain sockfd2 and data_bytes */
623	snprintf(extregex, sizeof(extregex),
624		"send.*0x%x.*return,success,%zd", sockfd2, data_bytes);
625	check_audit(fds, extregex, pipefd);
626
627	/* Close all socket descriptors */
628	close_sockets(3, sockfd, sockfd2, connectfd);
629}
630
631ATF_TC_CLEANUP(send_success, tc)
632{
633	cleanup();
634}
635
636
637ATF_TC_WITH_CLEANUP(send_failure);
638ATF_TC_HEAD(send_failure, tc)
639{
640	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
641					"send(2) call");
642}
643
644ATF_TC_BODY(send_failure, tc)
645{
646	snprintf(extregex, sizeof(extregex), "send.*%s", invalregex);
647	FILE *pipefd = setup(fds, auclass);
648	/* Failure reason: Invalid socket descriptor */
649	ATF_REQUIRE_EQ(-1, send(-1, NULL, 0, 0));
650	check_audit(fds, extregex, pipefd);
651}
652
653ATF_TC_CLEANUP(send_failure, tc)
654{
655	cleanup();
656}
657
658
659ATF_TC_WITH_CLEANUP(recv_success);
660ATF_TC_HEAD(recv_success, tc)
661{
662	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
663					"recv(2) call");
664}
665
666ATF_TC_BODY(recv_success, tc)
667{
668	assign_address(&server);
669	/* Setup a server socket and bind to the specified address */
670	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
671	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
672	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
673
674	/* Set up "blocking" client and connect with non-blocking server */
675	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
676	ATF_REQUIRE_EQ(0, connect(sockfd2, (struct sockaddr *)&server, len));
677	ATF_REQUIRE((connectfd = accept(sockfd, NULL, &len)) != -1);
678	/* Send a sample message to the connected socket */
679	ATF_REQUIRE(send(sockfd2, msgbuff, strlen(msgbuff), 0) != -1);
680
681	/* Receive data once connectfd is ready for reading */
682	FILE *pipefd = setup(fds, auclass);
683	ATF_REQUIRE((data_bytes = recv(connectfd, data, MAX_DATA, 0)) != 0);
684
685	/* Audit record must contain connectfd and data_bytes */
686	snprintf(extregex, sizeof(extregex),
687		"recv.*0x%x.*return,success,%zd", connectfd, data_bytes);
688	check_audit(fds, extregex, pipefd);
689
690	/* Close all socket descriptors */
691	close_sockets(3, sockfd, sockfd2, connectfd);
692}
693
694ATF_TC_CLEANUP(recv_success, tc)
695{
696	cleanup();
697}
698
699
700ATF_TC_WITH_CLEANUP(recv_failure);
701ATF_TC_HEAD(recv_failure, tc)
702{
703	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
704					"recv(2) call");
705}
706
707ATF_TC_BODY(recv_failure, tc)
708{
709	snprintf(extregex, sizeof(extregex), "recv.*%s", invalregex);
710	FILE *pipefd = setup(fds, auclass);
711	/* Failure reason: Invalid socket descriptor */
712	ATF_REQUIRE_EQ(-1, recv(-1, NULL, 0, 0));
713	check_audit(fds, extregex, pipefd);
714}
715
716ATF_TC_CLEANUP(recv_failure, tc)
717{
718	cleanup();
719}
720
721
722ATF_TC_WITH_CLEANUP(sendto_success);
723ATF_TC_HEAD(sendto_success, tc)
724{
725	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
726					"sendto(2) call");
727}
728
729ATF_TC_BODY(sendto_success, tc)
730{
731	assign_address(&server);
732	/*  Setup a server socket and bind to the specified address */
733	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
734	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
735
736	/* Set up client socket to be used for sending the data */
737	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
738
739	/* Send a sample message to server's address */
740	FILE *pipefd = setup(fds, auclass);
741	ATF_REQUIRE((data_bytes = sendto(sockfd2, msgbuff,
742		strlen(msgbuff), 0, (struct sockaddr *)&server, len)) != -1);
743
744	/* Audit record must contain sockfd2 and data_bytes */
745	snprintf(extregex, sizeof(extregex),
746		"sendto.*0x%x.*return,success,%zd", sockfd2, data_bytes);
747	check_audit(fds, extregex, pipefd);
748
749	/* Close all socket descriptors */
750	close_sockets(2, sockfd, sockfd2);
751}
752
753ATF_TC_CLEANUP(sendto_success, tc)
754{
755	cleanup();
756}
757
758
759ATF_TC_WITH_CLEANUP(sendto_failure);
760ATF_TC_HEAD(sendto_failure, tc)
761{
762	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
763					"sendto(2) call");
764}
765
766ATF_TC_BODY(sendto_failure, tc)
767{
768	snprintf(extregex, sizeof(extregex), "sendto.*%s", invalregex);
769	FILE *pipefd = setup(fds, auclass);
770	/* Failure reason: Invalid socket descriptor */
771	ATF_REQUIRE_EQ(-1, sendto(-1, NULL, 0, 0, NULL, 0));
772	check_audit(fds, extregex, pipefd);
773}
774
775ATF_TC_CLEANUP(sendto_failure, tc)
776{
777	cleanup();
778}
779
780
781ATF_TC_WITH_CLEANUP(recvfrom_success);
782ATF_TC_HEAD(recvfrom_success, tc)
783{
784	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
785					"recvfrom(2) call");
786}
787
788ATF_TC_BODY(recvfrom_success, tc)
789{
790	assign_address(&server);
791	/*  Setup a server socket and bind to the specified address */
792	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
793	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
794
795	/* Set up client socket to be used for sending the data */
796	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
797	ATF_REQUIRE(sendto(sockfd2, msgbuff, strlen(msgbuff), 0,
798		(struct sockaddr *)&server, len) != -1);
799
800	/* Receive data once sockfd is ready for reading */
801	FILE *pipefd = setup(fds, auclass);
802	ATF_REQUIRE((data_bytes = recvfrom(sockfd, data,
803		MAX_DATA, 0, NULL, &len)) != 0);
804
805	/* Audit record must contain sockfd and data_bytes */
806	snprintf(extregex, sizeof(extregex),
807		"recvfrom.*0x%x.*return,success,%zd", sockfd, data_bytes);
808	check_audit(fds, extregex, pipefd);
809
810	/* Close all socket descriptors */
811	close_sockets(2, sockfd, sockfd2);
812}
813
814ATF_TC_CLEANUP(recvfrom_success, tc)
815{
816	cleanup();
817}
818
819
820ATF_TC_WITH_CLEANUP(recvfrom_failure);
821ATF_TC_HEAD(recvfrom_failure, tc)
822{
823	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
824					"recvfrom(2) call");
825}
826
827ATF_TC_BODY(recvfrom_failure, tc)
828{
829	snprintf(extregex, sizeof(extregex), "recvfrom.*%s", invalregex);
830	FILE *pipefd = setup(fds, auclass);
831	/* Failure reason: Invalid socket descriptor */
832	ATF_REQUIRE_EQ(-1, recvfrom(-1, NULL, 0, 0, NULL, NULL));
833	check_audit(fds, extregex, pipefd);
834}
835
836ATF_TC_CLEANUP(recvfrom_failure, tc)
837{
838	cleanup();
839}
840
841
842ATF_TC_WITH_CLEANUP(sendmsg_success);
843ATF_TC_HEAD(sendmsg_success, tc)
844{
845	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
846					"recvmsg(2) call");
847}
848
849ATF_TC_BODY(sendmsg_success, tc)
850{
851	assign_address(&server);
852	/* Create a datagram server socket & bind to UNIX address family */
853	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
854	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
855
856	/* Message buffer to be sent to the server */
857	init_iov(&io1, msgbuff, sizeof(msgbuff));
858	init_msghdr(&sendbuf, &io1, &server);
859
860	/* Set up UDP client to communicate with the server */
861	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
862
863	/* Send a sample message to the specified client address */
864	FILE *pipefd = setup(fds, auclass);
865	ATF_REQUIRE((data_bytes = sendmsg(sockfd2, &sendbuf, 0)) != -1);
866
867	/* Audit record must contain sockfd2 and data_bytes */
868	snprintf(extregex, sizeof(extregex),
869		"sendmsg.*0x%x.*return,success,%zd", sockfd2, data_bytes);
870	check_audit(fds, extregex, pipefd);
871
872	/* Close all socket descriptors */
873	close_sockets(2, sockfd, sockfd2);
874}
875
876ATF_TC_CLEANUP(sendmsg_success, tc)
877{
878	cleanup();
879}
880
881
882ATF_TC_WITH_CLEANUP(sendmsg_failure);
883ATF_TC_HEAD(sendmsg_failure, tc)
884{
885	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
886					"sendmsg(2) call");
887}
888
889ATF_TC_BODY(sendmsg_failure, tc)
890{
891	snprintf(extregex, sizeof(extregex),
892		"sendmsg.*return,failure : Bad address");
893	FILE *pipefd = setup(fds, auclass);
894	ATF_REQUIRE_EQ(-1, sendmsg(-1, NULL, 0));
895	check_audit(fds, extregex, pipefd);
896}
897
898ATF_TC_CLEANUP(sendmsg_failure, tc)
899{
900	cleanup();
901}
902
903
904ATF_TC_WITH_CLEANUP(recvmsg_success);
905ATF_TC_HEAD(recvmsg_success, tc)
906{
907	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
908					"recvmsg(2) call");
909}
910
911ATF_TC_BODY(recvmsg_success, tc)
912{
913	assign_address(&server);
914	/* Create a datagram server socket & bind to UNIX address family */
915	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
916	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
917
918	/* Message buffer to be sent to the server */
919	init_iov(&io1, msgbuff, sizeof(msgbuff));
920	init_msghdr(&sendbuf, &io1, &server);
921
922	/* Prepare buffer to store the received data in */
923	init_iov(&io2, data, sizeof(data));
924	init_msghdr(&recvbuf, &io2, NULL);
925
926	/* Set up UDP client to communicate with the server */
927	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_DGRAM, 0)) != -1);
928	/* Send a sample message to the connected socket */
929	ATF_REQUIRE(sendmsg(sockfd2, &sendbuf, 0) != -1);
930
931	/* Receive data once clientfd is ready for reading */
932	FILE *pipefd = setup(fds, auclass);
933	ATF_REQUIRE((data_bytes = recvmsg(sockfd, &recvbuf, 0)) != -1);
934
935	/* Audit record must contain sockfd and data_bytes */
936	snprintf(extregex, sizeof(extregex),
937		"recvmsg.*%#x.*return,success,%zd", sockfd, data_bytes);
938	check_audit(fds, extregex, pipefd);
939
940	/* Close all socket descriptors */
941	close_sockets(2, sockfd, sockfd2);
942}
943
944ATF_TC_CLEANUP(recvmsg_success, tc)
945{
946	cleanup();
947}
948
949
950ATF_TC_WITH_CLEANUP(recvmsg_failure);
951ATF_TC_HEAD(recvmsg_failure, tc)
952{
953	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
954					"recvmsg(2) call");
955}
956
957ATF_TC_BODY(recvmsg_failure, tc)
958{
959	snprintf(extregex, sizeof(extregex),
960		"recvmsg.*return,failure : Bad address");
961	FILE *pipefd = setup(fds, auclass);
962	ATF_REQUIRE_EQ(-1, recvmsg(-1, NULL, 0));
963	check_audit(fds, extregex, pipefd);
964}
965
966ATF_TC_CLEANUP(recvmsg_failure, tc)
967{
968	cleanup();
969}
970
971
972ATF_TC_WITH_CLEANUP(shutdown_success);
973ATF_TC_HEAD(shutdown_success, tc)
974{
975	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
976					"shutdown(2) call");
977}
978
979ATF_TC_BODY(shutdown_success, tc)
980{
981	assign_address(&server);
982	/* Setup server socket and bind to the specified address */
983	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
984	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
985	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
986
987	/* Setup client and connect with the blocking server */
988	ATF_REQUIRE((sockfd2 = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
989	ATF_REQUIRE_EQ(0, connect(sockfd2, (struct sockaddr *)&server, len));
990	ATF_REQUIRE((connectfd = accept(sockfd, NULL, &len)) != -1);
991
992	/* Audit record must contain clientfd */
993	snprintf(extregex, sizeof(extregex),
994		"shutdown.*%#x.*return,success", connectfd);
995
996	FILE *pipefd = setup(fds, auclass);
997	ATF_REQUIRE_EQ(0, shutdown(connectfd, SHUT_RDWR));
998	check_audit(fds, extregex, pipefd);
999
1000	/* Close all socket descriptors */
1001	close_sockets(3, sockfd, sockfd2, connectfd);
1002}
1003
1004ATF_TC_CLEANUP(shutdown_success, tc)
1005{
1006	cleanup();
1007}
1008
1009
1010ATF_TC_WITH_CLEANUP(shutdown_failure);
1011ATF_TC_HEAD(shutdown_failure, tc)
1012{
1013	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
1014					"shutdown(2) call");
1015}
1016
1017ATF_TC_BODY(shutdown_failure, tc)
1018{
1019	pid = getpid();
1020	snprintf(extregex, sizeof(extregex),
1021		"shutdown.*%d.*return,failure", pid);
1022
1023	FILE *pipefd = setup(fds, auclass);
1024	/* Failure reason: Invalid socket descriptor */
1025	ATF_REQUIRE_EQ(-1, shutdown(-1, SHUT_RDWR));
1026	check_audit(fds, extregex, pipefd);
1027}
1028
1029ATF_TC_CLEANUP(shutdown_failure, tc)
1030{
1031	cleanup();
1032}
1033
1034
1035ATF_TC_WITH_CLEANUP(sendfile_success);
1036ATF_TC_HEAD(sendfile_success, tc)
1037{
1038	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
1039					"sendfile(2) call");
1040}
1041
1042ATF_TC_BODY(sendfile_success, tc)
1043{
1044	int filedesc;
1045	ATF_REQUIRE((filedesc = open(path, O_CREAT | O_RDONLY, mode)) != -1);
1046	/* Create a simple UNIX socket to send out random data */
1047	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
1048	/* Check the presence of sockfd, non-file in the audit record */
1049	snprintf(extregex, sizeof(extregex),
1050		"sendfile.*%#x,non-file.*return,success", filedesc);
1051
1052	FILE *pipefd = setup(fds, auclass);
1053	ATF_REQUIRE_EQ(0, sendfile(filedesc, sockfd, 0, 0, NULL, NULL, 0));
1054	check_audit(fds, extregex, pipefd);
1055
1056	/* Teardown socket and file descriptors */
1057	close_sockets(2, sockfd, filedesc);
1058}
1059
1060ATF_TC_CLEANUP(sendfile_success, tc)
1061{
1062	cleanup();
1063}
1064
1065
1066ATF_TC_WITH_CLEANUP(sendfile_failure);
1067ATF_TC_HEAD(sendfile_failure, tc)
1068{
1069	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
1070					"sendfile(2) call");
1071}
1072
1073ATF_TC_BODY(sendfile_failure, tc)
1074{
1075	pid = getpid();
1076	snprintf(extregex, sizeof(extregex),
1077		"sendfile.*%d.*return,failure", pid);
1078	FILE *pipefd = setup(fds, auclass);
1079	ATF_REQUIRE_EQ(-1, sendfile(-1, -1, 0, 0, NULL, NULL, 0));
1080	check_audit(fds, extregex, pipefd);
1081}
1082
1083ATF_TC_CLEANUP(sendfile_failure, tc)
1084{
1085	cleanup();
1086}
1087
1088
1089ATF_TC_WITH_CLEANUP(setfib_success);
1090ATF_TC_HEAD(setfib_success, tc)
1091{
1092	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
1093					"setfib(2) call");
1094}
1095
1096ATF_TC_BODY(setfib_success, tc)
1097{
1098	pid = getpid();
1099	snprintf(extregex, sizeof(extregex), "setfib.*%d.*return,success", pid);
1100
1101	FILE *pipefd = setup(fds, auclass);
1102	ATF_REQUIRE_EQ(0, setfib(0));
1103	check_audit(fds, extregex, pipefd);
1104}
1105
1106ATF_TC_CLEANUP(setfib_success, tc)
1107{
1108	cleanup();
1109}
1110
1111
1112ATF_TC_WITH_CLEANUP(setfib_failure);
1113ATF_TC_HEAD(setfib_failure, tc)
1114{
1115	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
1116					"setfib(2) call");
1117}
1118
1119ATF_TC_BODY(setfib_failure, tc)
1120{
1121	pid = getpid();
1122	snprintf(extregex, sizeof(extregex), "setfib.*%d.*return,failure", pid);
1123
1124	FILE *pipefd = setup(fds, auclass);
1125	ATF_REQUIRE_EQ(-1, setfib(-1));
1126	check_audit(fds, extregex, pipefd);
1127}
1128
1129ATF_TC_CLEANUP(setfib_failure, tc)
1130{
1131	cleanup();
1132}
1133
1134
1135ATF_TP_ADD_TCS(tp)
1136{
1137	ATF_TP_ADD_TC(tp, socket_success);
1138	ATF_TP_ADD_TC(tp, socket_failure);
1139	ATF_TP_ADD_TC(tp, socketpair_success);
1140	ATF_TP_ADD_TC(tp, socketpair_failure);
1141	ATF_TP_ADD_TC(tp, setsockopt_success);
1142	ATF_TP_ADD_TC(tp, setsockopt_failure);
1143
1144	ATF_TP_ADD_TC(tp, bind_success);
1145	ATF_TP_ADD_TC(tp, bind_failure);
1146	ATF_TP_ADD_TC(tp, bindat_success);
1147	ATF_TP_ADD_TC(tp, bindat_failure);
1148	ATF_TP_ADD_TC(tp, listen_success);
1149	ATF_TP_ADD_TC(tp, listen_failure);
1150
1151	ATF_TP_ADD_TC(tp, connect_success);
1152	ATF_TP_ADD_TC(tp, connect_failure);
1153	ATF_TP_ADD_TC(tp, connectat_success);
1154	ATF_TP_ADD_TC(tp, connectat_failure);
1155	ATF_TP_ADD_TC(tp, accept_success);
1156	ATF_TP_ADD_TC(tp, accept_failure);
1157
1158	ATF_TP_ADD_TC(tp, send_success);
1159	ATF_TP_ADD_TC(tp, send_failure);
1160	ATF_TP_ADD_TC(tp, recv_success);
1161	ATF_TP_ADD_TC(tp, recv_failure);
1162
1163	ATF_TP_ADD_TC(tp, sendto_success);
1164	ATF_TP_ADD_TC(tp, sendto_failure);
1165	ATF_TP_ADD_TC(tp, recvfrom_success);
1166	ATF_TP_ADD_TC(tp, recvfrom_failure);
1167
1168	ATF_TP_ADD_TC(tp, sendmsg_success);
1169	ATF_TP_ADD_TC(tp, sendmsg_failure);
1170	ATF_TP_ADD_TC(tp, recvmsg_success);
1171	ATF_TP_ADD_TC(tp, recvmsg_failure);
1172
1173	ATF_TP_ADD_TC(tp, shutdown_success);
1174	ATF_TP_ADD_TC(tp, shutdown_failure);
1175	ATF_TP_ADD_TC(tp, sendfile_success);
1176	ATF_TP_ADD_TC(tp, sendfile_failure);
1177	ATF_TP_ADD_TC(tp, setfib_success);
1178	ATF_TP_ADD_TC(tp, setfib_failure);
1179
1180	return (atf_no_error());
1181}
1182