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