Add basic pledge/unveil sandbox on OpenBSD
[tinc] / test / unit / test_proxy.c
1 #include "unittest.h"
2 #include "../../src/net.h"
3 #include "../../src/netutl.h"
4 #include "../../src/proxy.h"
5 #include "../../src/xalloc.h"
6
7 static const char *user = "foo";
8 static const size_t userlen = sizeof("foo") - 1;
9
10 static const char *pass = "bar";
11 static const size_t passlen = sizeof("bar") - 1;
12
13 static int teardown(void **state) {
14         (void)state;
15
16         free(proxyuser);
17         proxyuser = NULL;
18
19         free(proxypass);
20         proxypass = NULL;
21
22         free(proxyhost);
23         proxyhost = NULL;
24
25         return 0;
26 }
27
28 static void test_socks_req_len_socks4_ipv4(void **state) {
29         (void)state;
30
31         const sockaddr_t sa = str2sockaddr("127.0.0.1", "4242");
32
33         size_t len = socks_req_len(PROXY_SOCKS4, &sa);
34         assert_int_equal(9, len);
35
36         proxyuser = xstrdup(user);
37         len = socks_req_len(PROXY_SOCKS4, &sa);
38         assert_int_equal(9 + userlen, len);
39 }
40
41 static void test_socks_req_len_socks4_ipv6(void **state) {
42         (void)state;
43
44         sockaddr_t sa = str2sockaddr("::1", "4242");
45         size_t len = socks_req_len(PROXY_SOCKS4, &sa);
46         assert_int_equal(0, len);
47 }
48
49 static void test_socks_req_len_socks5_ipv4(void **state) {
50         (void)state;
51
52         sockaddr_t sa = str2sockaddr("127.0.0.1", "4242");
53         size_t baselen = 13;
54
55         // Base test
56         size_t len = socks_req_len(PROXY_SOCKS5, &sa);
57         assert_int_equal(baselen, len);
58
59         // Setting only password must not change result
60         proxypass = xstrdup(pass);
61         len = socks_req_len(PROXY_SOCKS5, &sa);
62         assert_int_equal(baselen, len);
63
64         // Setting both must
65         proxyuser = xstrdup(user);
66         len = socks_req_len(PROXY_SOCKS5, &sa);
67         assert_int_equal(baselen + 3 + userlen + passlen, len);
68 }
69
70 static void test_socks_req_len_socks5_ipv6(void **state) {
71         (void)state;
72
73         sockaddr_t sa = str2sockaddr("::1", "4242");
74         size_t baselen = 25;
75
76         // Base test
77         size_t len = socks_req_len(PROXY_SOCKS5, &sa);
78         assert_int_equal(baselen, len);
79
80         // Setting only user must not change result
81         proxyuser = xstrdup(user);
82         len = socks_req_len(PROXY_SOCKS5, &sa);
83         assert_int_equal(baselen, len);
84
85         // Setting both must
86         proxypass = xstrdup(pass);
87         len = socks_req_len(PROXY_SOCKS5, &sa);
88         assert_int_equal(baselen + 3 + userlen + passlen, len);
89 }
90
91 static void test_socks_req_len_wrong_types(void **state) {
92         (void)state;
93
94         sockaddr_t sa = str2sockaddr("::1", "4242");
95
96         assert_int_equal(0, socks_req_len(PROXY_NONE, &sa));
97         assert_int_equal(0, socks_req_len(PROXY_SOCKS4A, &sa));
98         assert_int_equal(0, socks_req_len(PROXY_HTTP, &sa));
99         assert_int_equal(0, socks_req_len(PROXY_EXEC, &sa));
100 }
101
102 static void test_socks_req_len_wrong_family(void **state) {
103         (void)state;
104
105         sockaddr_t sa = {.sa.sa_family = AF_UNKNOWN};
106         assert_int_equal(0, socks_req_len(PROXY_SOCKS4, &sa));
107         assert_int_equal(0, socks_req_len(PROXY_SOCKS5, &sa));
108 }
109
110 static void test_check_socks_resp_wrong_types(void **state) {
111         (void)state;
112
113         uint8_t buf[512] = {0};
114         assert_false(check_socks_resp(PROXY_NONE, buf, sizeof(buf)));
115         assert_false(check_socks_resp(PROXY_SOCKS4A, buf, sizeof(buf)));
116         assert_false(check_socks_resp(PROXY_HTTP, buf, sizeof(buf)));
117         assert_false(check_socks_resp(PROXY_EXEC, buf, sizeof(buf)));
118 }
119
120 PACKED(struct socks4_response {
121         uint8_t version;
122         uint8_t status;
123         uint16_t port;
124         uint32_t addr;
125 });
126
127 static const uint32_t localhost_ipv4 = 0x7F000001;
128
129 static void test_check_socks_resp_socks4_ok(void **state) {
130         (void)state;
131
132         const struct socks4_response resp = {
133                 .version = 0x00,
134                 .status = 0x5A,
135                 .port = htons(12345),
136                 .addr = htonl(localhost_ipv4),
137         };
138         assert_true(check_socks_resp(PROXY_SOCKS4, &resp, sizeof(resp)));
139 }
140
141 static void test_check_socks_resp_socks4_bad(void **state) {
142         (void)state;
143
144         const uint8_t short_len[] = {0x00, 0x5A};
145         assert_false(check_socks_resp(PROXY_SOCKS4, short_len, sizeof(short_len)));
146
147         const struct socks4_response bad_version = {
148                 .version = 0x01,
149                 .status = 0x5A,
150                 .port = htons(12345),
151                 .addr = htonl(0x7F000001),
152         };
153         assert_false(check_socks_resp(PROXY_SOCKS4, &bad_version, sizeof(bad_version)));
154
155         const struct socks4_response status_denied = {
156                 .version = 0x00,
157                 .status = 0x5B,
158                 .port = htons(12345),
159                 .addr = htonl(0x7F000001),
160         };
161         assert_false(check_socks_resp(PROXY_SOCKS4, &status_denied, sizeof(status_denied)));
162 }
163
164 PACKED(struct socks5_response {
165         struct {
166                 uint8_t socks_version;
167                 uint8_t auth_method;
168         } greet;
169
170         struct {
171                 uint8_t version;
172                 uint8_t status;
173         } auth;
174
175         struct {
176                 uint8_t socks_version;
177                 uint8_t status;
178                 uint8_t reserved;
179                 uint8_t addr_type;
180
181                 union {
182                         struct {
183                                 uint32_t addr;
184                                 uint16_t port;
185                         } ipv4;
186
187                         struct {
188                                 uint8_t addr[16];
189                                 uint16_t port;
190                         } ipv6;
191                 };
192         } resp;
193 });
194
195 PACKED(struct socks5_test_resp_t {
196         socks5_resp_t resp;
197
198         union {
199                 struct {
200                         uint32_t addr;
201                         uint16_t port;
202                 } ipv4;
203
204                 struct {
205                         uint8_t addr[16];
206                         uint16_t port;
207                 } ipv6;
208         };
209 });
210
211 typedef struct socks5_test_resp_t socks5_test_resp_t;
212
213 static socks5_test_resp_t *make_good_socks5_ipv4(void) {
214         static const socks5_test_resp_t reference = {
215                 .resp = {
216                         .choice = {.socks_version = 0x05, .auth_method = 0x02},
217                         .pass = {
218                                 .status = {.auth_version = 0x01, .auth_status = 0x00},
219                                 .resp = {
220                                         .socks_version = 0x05,
221                                         .conn_status = 0x00,
222                                         .reserved = 0x00,
223                                         .addr_type = 0x01,
224                                 },
225                         },
226                 },
227                 .ipv4 = {.addr = 0x01020304, .port = 0x123},
228         };
229
230         socks5_test_resp_t *result = xmalloc(sizeof(socks5_test_resp_t));
231         memcpy(result, &reference, sizeof(reference));
232         return result;
233 }
234
235 static socks5_test_resp_t *make_good_socks5_ipv6(void) {
236         static const socks5_test_resp_t reference = {
237                 .resp = {
238                         .choice = {.socks_version = 0x05, .auth_method = 0x02},
239                         .pass = {
240                                 .status = {.auth_version = 0x01, .auth_status = 0x00},
241                                 .resp = {
242                                         .socks_version = 0x05,
243                                         .conn_status = 0x00,
244                                         .reserved = 0x00,
245                                         .addr_type = 0x04,
246                                 },
247                         },
248                 },
249                 .ipv6 = {
250                         .addr = {
251                                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
252                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253                         },
254                         .port = 0x123,
255                 },
256         };
257
258         socks5_test_resp_t *result = xmalloc(sizeof(socks5_test_resp_t));
259         memcpy(result, &reference, sizeof(reference));
260         return result;
261 }
262
263 static void test_check_socks_resp_socks5_ok_ipv4(void **state) {
264         (void)state;
265
266         socks5_test_resp_t *resp = make_good_socks5_ipv4();
267         assert_true(check_socks_resp(PROXY_SOCKS5, resp, sizeof(*resp)));
268         free(resp);
269 }
270
271 static void test_check_socks_resp_socks5_ok_ipv6(void **state) {
272         (void)state;
273
274         socks5_test_resp_t *resp = make_good_socks5_ipv6();
275         assert_true(check_socks_resp(PROXY_SOCKS5, resp, sizeof(*resp)));
276         free(resp);
277 }
278
279 static void test_check_socks_resp_socks5_short(void **state) {
280         (void)state;
281
282         const uint8_t resp[] = {0x05, 0x02};
283         assert_false(check_socks_resp(PROXY_SOCKS5, resp, sizeof(resp)));
284 }
285
286 // Define a test that assigns a bad value to one of the fields and checks that it fails
287 #define BREAK_SOCKS5_FIELD_TEST(proto, name, expr)                                   \
288         static void test_check_socks_resp_socks5_bad_##name##_##proto(void **state) {    \
289                 (void)state;                                                                 \
290                 socks5_test_resp_t *resp = make_good_socks5_##proto();                       \
291                 assert_true(check_socks_resp(PROXY_SOCKS5, resp, sizeof(*resp)));            \
292                 expr;                                                                        \
293                 assert_false(check_socks_resp(PROXY_SOCKS5, resp, sizeof(*resp)));           \
294                 free(resp);                                                                  \
295         }
296
297 // Define a test group for IPv4 or IPv6
298 #define BREAK_SOCKS5_TEST_GROUP(proto) \
299         BREAK_SOCKS5_FIELD_TEST(proto, resp_socks_version,   resp->resp.pass.resp.socks_version = 0x4)  \
300         BREAK_SOCKS5_FIELD_TEST(proto, resp_conn_status,     resp->resp.pass.resp.conn_status = 0x1)    \
301         BREAK_SOCKS5_FIELD_TEST(proto, resp_addr_type,       resp->resp.pass.resp.addr_type = 0x42)     \
302         BREAK_SOCKS5_FIELD_TEST(proto, choice_socks_version, resp->resp.choice.socks_version = 0x04)    \
303         BREAK_SOCKS5_FIELD_TEST(proto, choice_auth_method,   resp->resp.choice.auth_method = 0x12)      \
304         BREAK_SOCKS5_FIELD_TEST(proto, status_auth_version,  resp->resp.pass.status.auth_version = 0x2) \
305         BREAK_SOCKS5_FIELD_TEST(proto, status_auth_status,   resp->resp.pass.status.auth_status = 0x1)
306
307 BREAK_SOCKS5_TEST_GROUP(ipv4)
308 BREAK_SOCKS5_TEST_GROUP(ipv6)
309
310 static void test_create_socks_req_socks4(void **state) {
311         (void)state;
312
313         const uint8_t ref[8] = {0x04, 0x01, 0x00, 0x7b, 0x01, 0x01, 0x01, 0x01};
314         const sockaddr_t sa = str2sockaddr("1.1.1.1", "123");
315
316         uint8_t buf[512];
317         assert_int_equal(sizeof(ref), create_socks_req(PROXY_SOCKS4, buf, &sa));
318         assert_memory_equal(ref, buf, sizeof(ref));
319 }
320
321 static void test_create_socks_req_socks5_ipv4_anon(void **state) {
322         (void) state;
323
324         const sockaddr_t sa = str2sockaddr("2.2.2.2", "16962");
325
326         const uint8_t ref[13] = {
327                 0x05, 0x01, 0x00,
328                 0x05, 0x01, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42,
329         };
330
331         uint8_t buf[sizeof(ref)];
332         assert_int_equal(12, create_socks_req(PROXY_SOCKS5, buf, &sa));
333         assert_memory_equal(ref, buf, sizeof(ref));
334 }
335
336 static void test_create_socks_req_socks5_ipv4_password(void **state) {
337         (void)state;
338
339         proxyuser = xstrdup(user);
340         proxypass = xstrdup(pass);
341
342         const sockaddr_t sa = str2sockaddr("2.2.2.2", "16962");
343
344         const uint8_t ref[22] = {
345                 0x05, 0x01, 0x02,
346                 0x01, (uint8_t)userlen, 'f', 'o', 'o', (uint8_t)passlen, 'b', 'a', 'r',
347                 0x05, 0x01, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x42, 0x42,
348         };
349
350         uint8_t buf[sizeof(ref)];
351         assert_int_equal(14, create_socks_req(PROXY_SOCKS5, buf, &sa));
352         assert_memory_equal(ref, buf, sizeof(ref));
353 }
354
355 static void test_create_socks_req_socks5_ipv6_anon(void **state) {
356         (void)state;
357
358         const sockaddr_t sa = str2sockaddr("1111:2222::3333:4444:5555", "18504");
359
360         const uint8_t ref[25] = {
361                 0x05, 0x01, 0x00,
362                 0x05, 0x01, 0x00, 0x04,
363                 0x11, 0x11, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55,
364                 0x48, 0x48,
365         };
366
367         uint8_t anon_buf[sizeof(ref)];
368         assert_int_equal(24, create_socks_req(PROXY_SOCKS5, anon_buf, &sa));
369         assert_memory_equal(ref, anon_buf, sizeof(ref));
370 }
371
372
373 static void test_create_socks_req_socks5_ipv6_password(void **state) {
374         (void)state;
375
376         proxyuser = xstrdup(user);
377         proxypass = xstrdup(pass);
378
379         const sockaddr_t sa = str2sockaddr("4444:2222::6666:4444:1212", "12850");
380
381         const uint8_t ref[34] = {
382                 0x05, 0x01, 0x02,
383                 0x01, (uint8_t)userlen, 'f', 'o', 'o', (uint8_t)passlen, 'b', 'a', 'r',
384                 0x05, 0x01, 0x00, 0x04,
385                 0x44, 0x44, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x44, 0x44, 0x12, 0x12,
386                 0x32, 0x32,
387         };
388
389         uint8_t anon_buf[sizeof(ref)];
390         assert_int_equal(26, create_socks_req(PROXY_SOCKS5, anon_buf, &sa));
391         assert_memory_equal(ref, anon_buf, sizeof(ref));
392 }
393
394 int main(void) {
395         const struct CMUnitTest tests[] = {
396                 cmocka_unit_test_teardown(test_socks_req_len_socks4_ipv4, teardown),
397                 cmocka_unit_test_teardown(test_socks_req_len_socks4_ipv6, teardown),
398                 cmocka_unit_test_teardown(test_socks_req_len_socks5_ipv4, teardown),
399                 cmocka_unit_test_teardown(test_socks_req_len_socks5_ipv6, teardown),
400                 cmocka_unit_test_teardown(test_socks_req_len_wrong_types, teardown),
401                 cmocka_unit_test_teardown(test_socks_req_len_wrong_family, teardown),
402
403                 cmocka_unit_test(test_check_socks_resp_wrong_types),
404                 cmocka_unit_test(test_check_socks_resp_socks4_ok),
405                 cmocka_unit_test(test_check_socks_resp_socks4_bad),
406                 cmocka_unit_test(test_check_socks_resp_socks5_ok_ipv4),
407                 cmocka_unit_test(test_check_socks_resp_socks5_ok_ipv6),
408                 cmocka_unit_test(test_check_socks_resp_socks5_short),
409
410                 cmocka_unit_test(test_check_socks_resp_socks5_bad_resp_socks_version_ipv4),
411                 cmocka_unit_test(test_check_socks_resp_socks5_bad_resp_conn_status_ipv4),
412                 cmocka_unit_test(test_check_socks_resp_socks5_bad_resp_addr_type_ipv4),
413                 cmocka_unit_test(test_check_socks_resp_socks5_bad_choice_socks_version_ipv4),
414                 cmocka_unit_test(test_check_socks_resp_socks5_bad_choice_auth_method_ipv4),
415                 cmocka_unit_test(test_check_socks_resp_socks5_bad_status_auth_version_ipv4),
416                 cmocka_unit_test(test_check_socks_resp_socks5_bad_status_auth_status_ipv4),
417
418                 cmocka_unit_test(test_check_socks_resp_socks5_bad_resp_socks_version_ipv6),
419                 cmocka_unit_test(test_check_socks_resp_socks5_bad_resp_conn_status_ipv6),
420                 cmocka_unit_test(test_check_socks_resp_socks5_bad_resp_addr_type_ipv6),
421                 cmocka_unit_test(test_check_socks_resp_socks5_bad_choice_socks_version_ipv6),
422                 cmocka_unit_test(test_check_socks_resp_socks5_bad_choice_auth_method_ipv6),
423                 cmocka_unit_test(test_check_socks_resp_socks5_bad_status_auth_version_ipv6),
424                 cmocka_unit_test(test_check_socks_resp_socks5_bad_status_auth_status_ipv6),
425
426                 cmocka_unit_test_teardown(test_create_socks_req_socks4, teardown),
427                 cmocka_unit_test_teardown(test_create_socks_req_socks5_ipv4_anon, teardown),
428                 cmocka_unit_test_teardown(test_create_socks_req_socks5_ipv4_password, teardown),
429                 cmocka_unit_test_teardown(test_create_socks_req_socks5_ipv6_anon, teardown),
430                 cmocka_unit_test_teardown(test_create_socks_req_socks5_ipv6_password, teardown),
431         };
432         return cmocka_run_group_tests(tests, NULL, NULL);
433 }