xref: /freebsd/tests/sys/audit/network.c (revision f1ed5c000c688cf9781b486134baf4ba25415efd)
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  * $FreeBSD$
26  */
27 
28 #include <sys/types.h>
29 #include <sys/socket.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 SERVER_PATH "server"
40 
41 static int sockfd;
42 static socklen_t len;
43 static struct pollfd fds[1];
44 static char extregex[80];
45 static const char *auclass = "nt";
46 static const char *nosupregex = "return,failure : Address family "
47 				"not supported by protocol family";
48 static const char *invalregex = "return,failur.*Socket operation on non-socket";
49 
50 /*
51  * Variadic function to close socket descriptors
52  */
53 static void
54 close_sockets(int count, ...)
55 {
56 	int sockd;
57 	va_list socklist;
58 	va_start(socklist, count);
59 	for (sockd = 0; sockd < count; sockd++) {
60 		close(va_arg(socklist, int));
61 	}
62 	va_end(socklist);
63 }
64 
65 /*
66  * Assign local filesystem address to a Unix domain socket
67  */
68 static void
69 assign_address(struct sockaddr_un *server)
70 {
71 	memset(server, 0, sizeof(*server));
72 	server->sun_family = AF_UNIX;
73 	strcpy(server->sun_path, SERVER_PATH);
74 }
75 
76 
77 ATF_TC_WITH_CLEANUP(socket_success);
78 ATF_TC_HEAD(socket_success, tc)
79 {
80 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
81 					"socket(2) call");
82 }
83 
84 ATF_TC_BODY(socket_success, tc)
85 {
86 	FILE *pipefd = setup(fds, auclass);
87 	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
88 	/* Check the presence of sockfd in audit record */
89 	snprintf(extregex, sizeof(extregex), "socket.*ret.*success,%d", sockfd);
90 	check_audit(fds, extregex, pipefd);
91 	close(sockfd);
92 }
93 
94 ATF_TC_CLEANUP(socket_success, tc)
95 {
96 	cleanup();
97 }
98 
99 
100 ATF_TC_WITH_CLEANUP(socket_failure);
101 ATF_TC_HEAD(socket_failure, tc)
102 {
103 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
104 					"socket(2) call");
105 }
106 
107 ATF_TC_BODY(socket_failure, tc)
108 {
109 	snprintf(extregex, sizeof(extregex), "socket.*%s", nosupregex);
110 	FILE *pipefd = setup(fds, auclass);
111 	/* Failure reason: Unsupported value of 'domain' argument: 0 */
112 	ATF_REQUIRE_EQ(-1, socket(0, SOCK_STREAM, 0));
113 	check_audit(fds, extregex, pipefd);
114 }
115 
116 ATF_TC_CLEANUP(socket_failure, tc)
117 {
118 	cleanup();
119 }
120 
121 
122 ATF_TC_WITH_CLEANUP(socketpair_success);
123 ATF_TC_HEAD(socketpair_success, tc)
124 {
125 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
126 					"socketpair(2) call");
127 }
128 
129 ATF_TC_BODY(socketpair_success, tc)
130 {
131 	int sv[2];
132 	FILE *pipefd = setup(fds, auclass);
133 	ATF_REQUIRE_EQ(0, socketpair(PF_UNIX, SOCK_STREAM, 0, sv));
134 
135 	/* Check for 0x0 (argument 3: default protocol) in the audit record */
136 	snprintf(extregex, sizeof(extregex), "socketpair.*0x0.*return,success");
137 	check_audit(fds, extregex, pipefd);
138 	close_sockets(2, sv[0], sv[1]);
139 }
140 
141 ATF_TC_CLEANUP(socketpair_success, tc)
142 {
143 	cleanup();
144 }
145 
146 
147 ATF_TC_WITH_CLEANUP(socketpair_failure);
148 ATF_TC_HEAD(socketpair_failure, tc)
149 {
150 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
151 					"socketpair(2) call");
152 }
153 
154 ATF_TC_BODY(socketpair_failure, tc)
155 {
156 	snprintf(extregex, sizeof(extregex), "socketpair.*%s", nosupregex);
157 	FILE *pipefd = setup(fds, auclass);
158 	/* Failure reason: Unsupported value of 'domain' argument: 0 */
159 	ATF_REQUIRE_EQ(-1, socketpair(0, SOCK_STREAM, 0, NULL));
160 	check_audit(fds, extregex, pipefd);
161 }
162 
163 ATF_TC_CLEANUP(socketpair_failure, tc)
164 {
165 	cleanup();
166 }
167 
168 
169 ATF_TC_WITH_CLEANUP(setsockopt_success);
170 ATF_TC_HEAD(setsockopt_success, tc)
171 {
172 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
173 					"setsockopt(2) call");
174 }
175 
176 ATF_TC_BODY(setsockopt_success, tc)
177 {
178 	int tr = 1;
179 	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
180 	/* Check the presence of sockfd in audit record */
181 	snprintf(extregex, sizeof(extregex),
182 			"setsockopt.*0x%x.*return,success", sockfd);
183 
184 	FILE *pipefd = setup(fds, auclass);
185 	ATF_REQUIRE_EQ(0, setsockopt(sockfd, SOL_SOCKET,
186 		SO_REUSEADDR, &tr, sizeof(int)));
187 	check_audit(fds, extregex, pipefd);
188 	close(sockfd);
189 }
190 
191 ATF_TC_CLEANUP(setsockopt_success, tc)
192 {
193 	cleanup();
194 }
195 
196 
197 ATF_TC_WITH_CLEANUP(setsockopt_failure);
198 ATF_TC_HEAD(setsockopt_failure, tc)
199 {
200 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
201 					"setsockopt(2) call");
202 }
203 
204 ATF_TC_BODY(setsockopt_failure, tc)
205 {
206 	int tr = 1;
207 	snprintf(extregex, sizeof(extregex), "setsockopt.*%s", invalregex);
208 	FILE *pipefd = setup(fds, auclass);
209 	/* Failure reason: Invalid socket descriptor */
210 	ATF_REQUIRE_EQ(-1, setsockopt(0, SOL_SOCKET,
211 			SO_REUSEADDR, &tr, sizeof(int)));
212 	check_audit(fds, extregex, pipefd);
213 }
214 
215 ATF_TC_CLEANUP(setsockopt_failure, tc)
216 {
217 	cleanup();
218 }
219 
220 
221 ATF_TC_WITH_CLEANUP(bind_success);
222 ATF_TC_HEAD(bind_success, tc)
223 {
224 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
225 					"bind(2) call");
226 }
227 
228 ATF_TC_BODY(bind_success, tc)
229 {
230 	struct sockaddr_un server;
231 	assign_address(&server);
232 	len = sizeof(struct sockaddr_un);
233 
234 	/* Preliminary socket setup */
235 	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
236 	/* Check the presence of AF_UNIX address path in audit record */
237 	snprintf(extregex, sizeof(extregex),
238 		"bind.*unix.*%s.*return,success", SERVER_PATH);
239 
240 	FILE *pipefd = setup(fds, auclass);
241 	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
242 	check_audit(fds, extregex, pipefd);
243 	close(sockfd);
244 }
245 
246 ATF_TC_CLEANUP(bind_success, tc)
247 {
248 	cleanup();
249 }
250 
251 
252 ATF_TC_WITH_CLEANUP(bind_failure);
253 ATF_TC_HEAD(bind_failure, tc)
254 {
255 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
256 					"bind(2) call");
257 }
258 
259 ATF_TC_BODY(bind_failure, tc)
260 {
261 	/* Preliminary socket setup */
262 	struct sockaddr_un server;
263 	assign_address(&server);
264 	len = sizeof(struct sockaddr_un);
265 	/* Check the presence of AF_UNIX path in audit record */
266 	snprintf(extregex, sizeof(extregex),
267 			"bind.*%s.*return,failure", SERVER_PATH);
268 
269 	FILE *pipefd = setup(fds, auclass);
270 	/* Failure reason: Invalid socket descriptor */
271 	ATF_REQUIRE_EQ(-1, bind(0, (struct sockaddr *)&server, len));
272 	check_audit(fds, extregex, pipefd);
273 }
274 
275 ATF_TC_CLEANUP(bind_failure, tc)
276 {
277 	cleanup();
278 }
279 
280 
281 ATF_TC_WITH_CLEANUP(bindat_success);
282 ATF_TC_HEAD(bindat_success, tc)
283 {
284 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
285 					"bindat(2) call");
286 }
287 
288 ATF_TC_BODY(bindat_success, tc)
289 {
290 	struct sockaddr_un server;
291 	assign_address(&server);
292 	len = sizeof(struct sockaddr_un);
293 
294 	/* Preliminary socket setup */
295 	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
296 	/* Check the presence of socket descriptor in audit record */
297 	snprintf(extregex, sizeof(extregex),
298 			"bindat.*0x%x.*return,success", sockfd);
299 
300 	FILE *pipefd = setup(fds, auclass);
301 	ATF_REQUIRE_EQ(0, bindat(AT_FDCWD, sockfd,
302 			(struct sockaddr *)&server, len));
303 	check_audit(fds, extregex, pipefd);
304 	close(sockfd);
305 }
306 
307 ATF_TC_CLEANUP(bindat_success, tc)
308 {
309 	cleanup();
310 }
311 
312 
313 ATF_TC_WITH_CLEANUP(bindat_failure);
314 ATF_TC_HEAD(bindat_failure, tc)
315 {
316 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
317 					"bindat(2) call");
318 }
319 
320 ATF_TC_BODY(bindat_failure, tc)
321 {
322 	/* Preliminary socket setup */
323 	struct sockaddr_un server;
324 	assign_address(&server);
325 	len = sizeof(struct sockaddr_un);
326 	snprintf(extregex, sizeof(extregex), "bindat.*%s", invalregex);
327 
328 	FILE *pipefd = setup(fds, auclass);
329 	/* Failure reason: Invalid socket descriptor */
330 	ATF_REQUIRE_EQ(-1, bindat(AT_FDCWD, 0,
331 			(struct sockaddr *)&server, len));
332 	check_audit(fds, extregex, pipefd);
333 }
334 
335 ATF_TC_CLEANUP(bindat_failure, tc)
336 {
337 	cleanup();
338 }
339 
340 
341 ATF_TC_WITH_CLEANUP(listen_success);
342 ATF_TC_HEAD(listen_success, tc)
343 {
344 	atf_tc_set_md_var(tc, "descr", "Tests the audit of a successful "
345 					"listen(2) call");
346 }
347 
348 ATF_TC_BODY(listen_success, tc)
349 {
350 	struct sockaddr_un server;
351 	assign_address(&server);
352 	len = sizeof(struct sockaddr_un);
353 
354 	/* Preliminary socket setup */
355 	ATF_REQUIRE((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) != -1);
356 	ATF_REQUIRE_EQ(0, bind(sockfd, (struct sockaddr *)&server, len));
357 	/* Check the presence of socket descriptor in the audit record */
358 	snprintf(extregex, sizeof(extregex),
359 			"listen.*0x%x.*return,success", sockfd);
360 
361 	FILE *pipefd = setup(fds, auclass);
362 	ATF_REQUIRE_EQ(0, listen(sockfd, 1));
363 	check_audit(fds, extregex, pipefd);
364 	close(sockfd);
365 }
366 
367 ATF_TC_CLEANUP(listen_success, tc)
368 {
369 	cleanup();
370 }
371 
372 
373 ATF_TC_WITH_CLEANUP(listen_failure);
374 ATF_TC_HEAD(listen_failure, tc)
375 {
376 	atf_tc_set_md_var(tc, "descr", "Tests the audit of an unsuccessful "
377 					"listen(2) call");
378 }
379 
380 ATF_TC_BODY(listen_failure, tc)
381 {
382 	snprintf(extregex, sizeof(extregex), "listen.*%s", invalregex);
383 	FILE *pipefd = setup(fds, auclass);
384 	/* Failure reason: Invalid socket descriptor */
385 	ATF_REQUIRE_EQ(-1, listen(0, 1));
386 	check_audit(fds, extregex, pipefd);
387 }
388 
389 ATF_TC_CLEANUP(listen_failure, tc)
390 {
391 	cleanup();
392 }
393 
394 
395 ATF_TP_ADD_TCS(tp)
396 {
397 	ATF_TP_ADD_TC(tp, socket_success);
398 	ATF_TP_ADD_TC(tp, socket_failure);
399 	ATF_TP_ADD_TC(tp, socketpair_success);
400 	ATF_TP_ADD_TC(tp, socketpair_failure);
401 	ATF_TP_ADD_TC(tp, setsockopt_success);
402 	ATF_TP_ADD_TC(tp, setsockopt_failure);
403 
404 	ATF_TP_ADD_TC(tp, bind_success);
405 	ATF_TP_ADD_TC(tp, bind_failure);
406 	ATF_TP_ADD_TC(tp, bindat_success);
407 	ATF_TP_ADD_TC(tp, bindat_failure);
408 	ATF_TP_ADD_TC(tp, listen_success);
409 	ATF_TP_ADD_TC(tp, listen_failure);
410 
411 	return (atf_no_error());
412 }
413