1 /* Copyright (C) 2020-2021 Greenbone Networks GmbH
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 #include "pcap.c"
20
21 #include <cgreen/cgreen.h>
22 #include <cgreen/mocks.h>
23 #include <gvm/base/hosts.h>
24
25 Describe (pcap);
BeforeEach(pcap)26 BeforeEach (pcap)
27 {
28 cgreen_mocks_are (loose_mocks);
29 }
AfterEach(pcap)30 AfterEach (pcap)
31 {
32 }
33
34 __attribute__ ((weak)) int
35 __real_socket (__attribute__ ((unused)) int domain,
36 __attribute__ ((unused)) int type,
37 __attribute__ ((unused)) int protocol);
38
39 __attribute__ ((weak)) int
40 __real_setsockopt (__attribute__ ((unused)) int sockfd,
41 __attribute__ ((unused)) int level,
42 __attribute__ ((unused)) int optname,
43 __attribute__ ((unused)) const void *optval,
44 __attribute__ ((unused)) socklen_t optlen);
45
46 bool g_socket_use_real = true;
47 int
__wrap_socket(int domain,int type,int protocol)48 __wrap_socket (__attribute__ ((unused)) int domain,
49 __attribute__ ((unused)) int type,
50 __attribute__ ((unused)) int protocol)
51 {
52 if (g_socket_use_real)
53 return __real_socket (domain, type, protocol);
54
55 return (int) mock (domain, type, protocol);
56 }
57
58 bool g_setsockopt_use_real = true;
59 int
__wrap_setsockopt(int sockfd,int level,int optname,const void * optval,socklen_t optlen)60 __wrap_setsockopt (__attribute__ ((unused)) int sockfd,
61 __attribute__ ((unused)) int level,
62 __attribute__ ((unused)) int optname,
63 __attribute__ ((unused)) const void *optval,
64 __attribute__ ((unused)) socklen_t optlen)
65 {
66 if (g_setsockopt_use_real)
67 return __real_setsockopt (sockfd, level, optname, optval, optlen);
68
69 return (int) mock (sockfd, level, optname, optval, optlen);
70 }
71
72 /* If dst for routethrough() is localhost "lo" interface is returned. */
Ensure(pcap,routethrough_dst_is_localhost)73 Ensure (pcap, routethrough_dst_is_localhost)
74 {
75 /* setup */
76 g_socket_use_real = false;
77 gchar *interface = NULL;
78 gchar *ipv4_str = "127.0.0.1";
79 gvm_host_t *gvm_host = NULL;
80 struct in6_addr dst6;
81 struct in6_addr *dst6_p = &dst6;
82 struct in_addr dst4;
83 struct in_addr *dst4_p = &dst4;
84 assert_that ((gvm_host = gvm_host_from_str (ipv4_str)), is_not_null);
85 assert_that (gvm_host_get_addr6 ((gvm_host_t *) gvm_host, dst6_p),
86 is_equal_to (0));
87 assert_that (dst6_p, is_not_null);
88 dst4.s_addr = dst6_p->s6_addr32[3];
89
90 interface = routethrough (dst4_p, NULL);
91 (void) interface;
92
93 /* dependent on local environment */
94 // assert_that ((interface = routethrough (dst4_p, NULL)), is_not_null);
95 // assert_that (interface, is_equal_to_string ("lo"));
96 g_socket_use_real = true;
97 }
98
99 /* If dst is not null for routethrough() then another interface than "lo" is
100 * returned. */
Ensure(pcap,routethrough_dst_is_not_localhost)101 Ensure (pcap, routethrough_dst_is_not_localhost)
102 {
103 g_socket_use_real = false;
104 /* setup */
105 gchar *interface = NULL;
106 gchar *ipv4_str = "93.184.216.34"; /* example.com */
107 gvm_host_t *gvm_host = NULL;
108 struct in6_addr dst6;
109 struct in6_addr *dst6_p = &dst6;
110 struct in_addr dst4;
111 struct in_addr *dst4_p = &dst4;
112 assert_that ((gvm_host = gvm_host_from_str (ipv4_str)), is_not_null);
113 assert_that (gvm_host_get_addr6 ((gvm_host_t *) gvm_host, dst6_p),
114 is_equal_to (0));
115 assert_that (dst6_p, is_not_null);
116 dst4.s_addr = dst6_p->s6_addr32[3];
117
118 interface = routethrough (dst4_p, NULL);
119 assert_that (interface, is_not_equal_to_string ("lo"));
120 g_socket_use_real = true;
121 }
122
123 /* If neither dst nor src address are given to routethrough NULL is returned. */
Ensure(pcap,routethrough_no_src_dst_given)124 Ensure (pcap, routethrough_no_src_dst_given)
125 {
126 gchar *interface = NULL;
127 assert_that ((interface = routethrough (NULL, NULL)), is_null);
128 }
129
130 /* If global_source_addr is present then routethrough writes it into src. */
Ensure(pcap,routethrough_src_globalsource_set)131 Ensure (pcap, routethrough_src_globalsource_set)
132 {
133 /* setup */
134 g_socket_use_real = false;
135 cgreen_mocks_are (learning_mocks);
136
137 struct in_addr src = {.s_addr = 0}; /* ip src */
138 gchar *interface = NULL;
139 struct in_addr dst;
140 inet_pton (AF_INET, "93.184.216.34", &(dst.s_addr));
141
142 /* global source address set */
143 gvm_source_iface_init ("lo"); // lo is set but not really used after being set
144 /* dst not given */
145 assert_that ((interface = routethrough (NULL, &src)), is_null);
146 assert_that ((src.s_addr == INADDR_ANY));
147 /* dst localhost given */
148 src.s_addr = 0;
149
150 interface = routethrough (&dst, &src);
151 /* dependent on local environment */
152 // assert_that ((interface = routethrough (&dst, &src)), is_not_null);
153 assert_that (interface, is_not_equal_to_string ("lo"));
154 assert_that ((src.s_addr != INADDR_ANY));
155 g_socket_use_real = true;
156 }
157
158 /* If global_source_addr is not present then routethrough writes it into src. */
Ensure(pcap,routethrough_src_globalsource_not_set)159 Ensure (pcap, routethrough_src_globalsource_not_set)
160 {
161 g_socket_use_real = false;
162
163 struct in_addr src = {.s_addr = 0}; /* ip src */
164 gchar *interface = NULL;
165 struct in_addr dst;
166 inet_pton (AF_INET, "127.0.0.1", &(dst.s_addr));
167
168 /* global source address not set */
169 gvm_source_iface_init (NULL);
170 /* dst not given */
171 assert_that ((interface = routethrough (NULL, &src)), is_null);
172 assert_that ((src.s_addr == INADDR_ANY));
173 /* dst localhost given */
174 src.s_addr = 0;
175
176 interface = routethrough (&dst, &src);
177 /* dependent on local environment */
178 // assert_that ((interface = routethrough (&dst, &src)), is_not_null);
179 // assert_that (interface, is_equal_to_string ("lo"));
180 assert_that ((src.s_addr != INADDR_ANY));
181 g_socket_use_real = true;
182 }
183
Ensure(pcap,v6_islocalhost)184 Ensure (pcap, v6_islocalhost)
185 {
186 /* IPv4 */
187 struct in_addr addr;
188 struct sockaddr_in sin;
189 memset (&sin, 0, sizeof (struct sockaddr_in));
190 sin.sin_family = AF_INET;
191
192 /* example.com */
193 inet_pton (AF_INET, "93.184.216.34", &(addr.s_addr));
194
195 /* IPv6 */
196 struct in6_addr addr_6;
197
198 inet_pton (AF_INET6, "::FFFF:127.0.0.1", &(addr_6));
199 assert_that (v6_islocalhost (&addr_6), is_true);
200 inet_pton (AF_INET6, "::FFFF:0.0.0.0", &(addr_6));
201 assert_that (v6_islocalhost (&addr_6), is_true);
202 inet_pton (AF_INET6, "::FFFF:127.100.5.99", &(addr_6));
203 assert_that (v6_islocalhost (&addr_6), is_true);
204 /* loopback address */
205 inet_pton (AF_INET6, "0:0:0:0:0:0:0:1", &(addr_6));
206 assert_that (v6_islocalhost (&addr_6), is_true);
207
208 /* dependent on local environment */
209 // inet_pton (AF_INET6, <some local interface address>, &(addr_6));
210 // assert_that (v6_islocalhost (&addr_6), is_true);
211
212 /* example.com */
213 inet_pton (AF_INET6, "2606:2800:220:1:248:1893:25c8:1946", &(addr_6));
214 assert_that (v6_islocalhost (&addr_6), is_false);
215 }
216
Ensure(pcap,islocalhost)217 Ensure (pcap, islocalhost)
218 {
219 /* IPv4 */
220 struct in_addr addr;
221
222 inet_pton (AF_INET, "127.0.0.1", &(addr.s_addr));
223 assert_that (islocalhost (&addr), is_true);
224 inet_pton (AF_INET, "0.0.0.0", &(addr.s_addr));
225 assert_that (islocalhost (&addr), is_true);
226 inet_pton (AF_INET, "127.100.5.99", &(addr.s_addr));
227 assert_that (islocalhost (&addr), is_true);
228
229 /* dependent on local environment */
230 // // inet_pton (AF_INET, <some local interface address>, &(addr));
231 // // assert_that (islocalhost (&addr), is_true);
232
233 /* example.com */
234 inet_pton (AF_INET, "93.184.216.34", &(addr.s_addr));
235 assert_that (islocalhost (&addr), is_false);
236 }
237
238 /**
239 * @brief Apply mask to dest addr.
240 *
241 * @param[out] network Masked dest addr.
242 * @param[in] dest Destination addr.
243 * @param[in] mask Mask to apply.
244 */
245 static void
apply_ipv6_mask(struct in6_addr * network,struct in6_addr * dest,struct in6_addr * mask)246 apply_ipv6_mask (struct in6_addr *network, struct in6_addr *dest,
247 struct in6_addr *mask)
248 {
249 for (int i = 0; i < (int) sizeof (struct in6_addr); i++)
250 network->s6_addr[i] = dest->s6_addr[i] & mask->s6_addr[i];
251 }
252
Ensure(pcap,ipv6_prefix_to_mask)253 Ensure (pcap, ipv6_prefix_to_mask)
254 {
255 struct in6_addr dest;
256 struct in6_addr result;
257 struct in6_addr mask;
258 struct in6_addr network;
259 const uint8_t byte_options[9] = {0xFF, 0x00, 0x80, 0xC0, 0xE0,
260 0xF0, 0xF8, 0xFC, 0xFE};
261
262 // create dst addr
263 const uint8_t addr_in[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
264 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
265 memcpy (dest.s6_addr, addr_in, sizeof addr_in);
266 // create expected result addr
267 const uint8_t result_in[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
268 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
269 0xFF, 0xFF, 0xFF, 0xFF};
270 memcpy (result.s6_addr, result_in, sizeof result_in);
271
272 // check every possible bit mask
273 for (int i = 128; i > 0; i--)
274 {
275 ipv6_prefix_to_mask (i, &mask);
276 apply_ipv6_mask (&network, &dest, &mask);
277 int byte_to_modify = i / 8;
278 if (byte_to_modify != 16)
279 result.s6_addr[byte_to_modify] = byte_options[(i % 8) + 1];
280
281 assert_that (IN6_ARE_ADDR_EQUAL (&network, &result));
282 }
283 }
284
285 TestSuite *
openvas_routethrough()286 openvas_routethrough ()
287 {
288 TestSuite *suite = create_test_suite ();
289 add_test_with_context (suite, pcap, routethrough_dst_is_localhost);
290 add_test_with_context (suite, pcap, routethrough_dst_is_not_localhost);
291 add_test_with_context (suite, pcap, routethrough_no_src_dst_given);
292 add_test_with_context (suite, pcap, routethrough_src_globalsource_set);
293 add_test_with_context (suite, pcap, routethrough_src_globalsource_not_set);
294 add_test_with_context (suite, pcap, v6_islocalhost);
295 add_test_with_context (suite, pcap, islocalhost);
296 add_test_with_context (suite, pcap, ipv6_prefix_to_mask);
297
298 return suite;
299 }
300
301 int
main(int argc,char ** argv)302 main (int argc, char **argv)
303 {
304 TestSuite *suite;
305
306 suite = create_test_suite ();
307 add_suite (suite, openvas_routethrough ());
308
309 if (argc > 1)
310 return run_single_test (suite, argv[1], create_text_reporter ());
311
312 return run_test_suite (suite, create_text_reporter ());
313 }
314