]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/audit/network.c
MFC many audit(4) tests.
[FreeBSD/FreeBSD.git] / tests / sys / audit / network.c
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 }