OpenVPN
test_push_update_msg.c
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdlib.h>
6#include <stdarg.h>
7#include <setjmp.h>
8#include <cmocka.h>
9#include "push.h"
10#include "options_util.h"
11#include "multi.h"
12
13/* mocks */
14
15void
16throw_signal_soft(const int signum, const char *signal_text)
17{
18 msg(M_WARN, "Offending option received from server");
19}
20
21unsigned int
30
31void
32update_vhash(struct multi_context *m, struct multi_instance *mi, const char *old_ip, const char *old_ipv6)
33{
34 return;
35}
36
37bool
39{
40 return true;
41}
42
43bool
44apply_push_options(struct context *c, struct options *options, struct buffer *buf,
45 unsigned int permission_mask, unsigned int *option_types_found,
46 struct env_set *es, bool is_update)
47{
48 char line[OPTION_PARM_SIZE];
49
50 while (buf_parse(buf, ',', line, sizeof(line)))
51 {
52 unsigned int push_update_option_flags = 0;
53 int i = 0;
54
55 if (is_update || options->pull_filter_list)
56 {
57 /* skip leading spaces matching the behaviour of parse_line */
58 while (isspace(line[i]))
59 {
60 i++;
61 }
62
63 if ((is_update && !check_push_update_option_flags(line, &i, &push_update_option_flags))
65 {
66 if (push_update_option_flags & PUSH_OPT_OPTIONAL)
67 {
68 continue; /* Ignoring this option */
69 }
70 return false; /* Cause push/pull error and stop push processing */
71 }
72 }
73 /*
74 * No need to test also the application part here
75 * (add_option/remove_option/update_option)
76 */
77 }
78 return true;
79}
80
81int
83 bool honor_received_options, unsigned int permission_mask,
84 unsigned int *option_types_found)
85{
86 struct buffer buf = *buffer;
87
88 if (buf_string_compare_advance(&buf, "PUSH_REQUEST"))
89 {
90 return PUSH_MSG_REQUEST;
91 }
93 {
94 return PUSH_MSG_REPLY;
95 }
97 {
98 return process_incoming_push_update(c, permission_mask, option_types_found, &buf, false);
99 }
100 else
101 {
102 return PUSH_MSG_ERROR;
103 }
104}
105
106const char *
107tls_common_name(const struct tls_multi *multi, const bool null)
108{
109 return NULL;
110}
111
112#ifndef ENABLE_MANAGEMENT
113bool
114send_control_channel_string(struct context *c, const char *str, int msglevel)
115{
116 return true;
117}
118#else /* ifndef ENABLE_MANAGEMENT */
119char **res;
120int i;
121
122bool
123send_control_channel_string(struct context *c, const char *str, int msglevel)
124{
125 if (res && res[i] && strcmp(res[i], str))
126 {
127 printf("\n\nexpected: %s\n\n actual: %s\n\n", res[i], str);
128 return false;
129 }
130 i++;
131 return true;
132}
133
134struct multi_instance *
135lookup_by_cid(struct multi_context *m, const unsigned long cid)
136{
137 return *(m->instances);
138}
139
140bool
142 const struct openvpn_sockaddr *osaddr,
143 bool use_port)
144{
145 return true;
146}
147#endif /* ifndef ENABLE_MANAGEMENT */
148
149/* tests */
150
151static void
153{
154 struct context *c = *state;
155 struct buffer buf = alloc_buf(256);
156 const char *update_msg =
157 "PUSH_UPDATE,dhcp-option DNS 8.8.8.8, route 0.0.0.0 0.0.0.0 10.10.10.1";
159 unsigned int option_types_found = 0;
160
162 &option_types_found),
164
165 free_buf(&buf);
166}
167
168static void
170{
171 struct context *c = *state;
172 struct buffer buf = alloc_buf(256);
173 const char *update_msg = "PUSH_UPDATEerr,dhcp-option DNS 8.8.8.8";
175 unsigned int option_types_found = 0;
176
178 &option_types_found),
180
181 free_buf(&buf);
182}
183
184static void
186{
187 struct context *c = *state;
188 struct buffer buf = alloc_buf(256);
189 const char *update_msg = "PUSH_UPDATE ,dhcp-option DNS 8.8.8.8";
191 unsigned int option_types_found = 0;
192
194 &option_types_found),
196
197 free_buf(&buf);
198}
199
200static void
202{
203 struct context *c = *state;
204 struct buffer buf = alloc_buf(256);
205 const char *update_msg = "PUSH_UPDATE, -?dns, route something, ?dhcp-option DNS 8.8.8.8";
207 unsigned int option_types_found = 0;
208
210 &option_types_found),
212
213 free_buf(&buf);
214}
215
216static void
218{
219 struct context *c = *state;
220 struct buffer buf = alloc_buf(256);
221 const char *update_msg = "PUSH_UPDATE, -dhcp-option, ?-dns";
223 unsigned int option_types_found = 0;
224
226 &option_types_found),
228
229 free_buf(&buf);
230}
231
232static void
234{
235 struct context *c = *state;
236 struct buffer buf = alloc_buf(256);
237 const char *update_msg = "PUSH_UPDATE, dev tun";
239 unsigned int option_types_found = 0;
240
242 &option_types_found),
244
245 free_buf(&buf);
246}
247
248static void
250{
251 struct context *c = *state;
252 struct buffer buf = alloc_buf(256);
253 const char *update_msg =
254 "PUSH_UPDATE,-dhcp-option, route 10.10.10.0, dhcp-option DNS 1.1.1.1, route 10.11.12.0, dhcp-option DOMAIN corp.local, keepalive 10 60";
256 unsigned int option_types_found = 0;
257
259 &option_types_found),
261
262 free_buf(&buf);
263}
264
265static void
267{
268 struct context *c = *state;
269 struct buffer buf = alloc_buf(256);
270 const char *update_msg =
271 "PUSH_UPDATE,-dhcp-option,dhcp-option DNS 8.8.8.8,redirect-gateway local,route 192.168.1.0 255.255.255.0";
273 unsigned int option_types_found = 0;
274
276 &option_types_found),
278
279 free_buf(&buf);
280}
281
282#ifdef ENABLE_MANAGEMENT
283char *r0[] = {
284 "PUSH_UPDATE,redirect-gateway local,route 192.168.1.0 255.255.255.0"
285};
286char *r1[] = {
287 "PUSH_UPDATE,-dhcp-option,blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,push-continuation 2",
288 "PUSH_UPDATE, akakakakakakakakakakakaf, dhcp-option DNS 8.8.8.8,redirect-gateway local,push-continuation 2",
289 "PUSH_UPDATE,route 192.168.1.0 255.255.255.0,push-continuation 1"
290};
291char *r3[] = {
292 "PUSH_UPDATE,,,"
293};
294char *r4[] = {
295 "PUSH_UPDATE,-dhcp-option, blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,push-continuation 2",
296 "PUSH_UPDATE, akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8, redirect-gateway local,push-continuation 2",
297 "PUSH_UPDATE, route 192.168.1.0 255.255.255.0,,push-continuation 1"
298};
299char *r5[] = {
300 "PUSH_UPDATE,,-dhcp-option, blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,push-continuation 2",
301 "PUSH_UPDATE, akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8, redirect-gateway local,push-continuation 2",
302 "PUSH_UPDATE, route 192.168.1.0 255.255.255.0,push-continuation 1"
303};
304char *r6[] = {
305 "PUSH_UPDATE,-dhcp-option,blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,push-continuation 2",
306 "PUSH_UPDATE, akakakakakakakakakakakaf, dhcp-option DNS 8.8.8.8, redirect-gateway 10.10.10.10,,push-continuation 2",
307 "PUSH_UPDATE, route 192.168.1.0 255.255.255.0,,push-continuation 1"
308};
309char *r7[] = {
310 "PUSH_UPDATE,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,push-continuation 2",
311 "PUSH_UPDATE,,,,,,,,,,,,,,,,,,,push-continuation 1"
312};
313char *r8[] = {
314 "PUSH_UPDATE,-dhcp-option,blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,push-continuation 2",
315 "PUSH_UPDATE, akakakakakakakakakakakaf, dhcp-option DNS 8.8.8.8,redirect-gateway\n local,push-continuation 2",
316 "PUSH_UPDATE,route 192.168.1.0 255.255.255.0\n\n\n,push-continuation 1"
317};
318char *r9[] = {
319 "PUSH_UPDATE,,"
320};
321
322
323const char *msg0 = "redirect-gateway local,route 192.168.1.0 255.255.255.0";
324const char *msg1 = "-dhcp-option,blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,"
325 " akakakakakakakakakakakaf, dhcp-option DNS 8.8.8.8,redirect-gateway local,route 192.168.1.0 255.255.255.0";
326const char *msg2 = "";
327const char *msg3 = ",,";
328const char *msg4 = "-dhcp-option, blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,"
329 " akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8, redirect-gateway local, route 192.168.1.0 255.255.255.0,";
330const char *msg5 = ",-dhcp-option, blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf,"
331 " akakakakakakakakakakakaf,dhcp-option DNS 8.8.8.8, redirect-gateway local, route 192.168.1.0 255.255.255.0";
332const char *msg6 = "-dhcp-option,blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf, akakakakakakakakakakakaf,"
333 " dhcp-option DNS 8.8.8.8, redirect-gateway 10.10.10.10,, route 192.168.1.0 255.255.255.0,";
334const char *msg7 = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,";
335const char *msg8 = "-dhcp-option,blablalalalalalalalalalalalalf, lalalalalalalalalalalalalalaf, akakakakakakakakakakakaf,"
336 " dhcp-option DNS 8.8.8.8,redirect-gateway\n local,route 192.168.1.0 255.255.255.0\n\n\n";
337const char *msg9 = ",";
338
339const char *msg10 = "abandon ability able about above absent absorb abstract absurd abuse access accident account accuse achieve"
340 "acid acoustic acquire across act action actor actress actual adapt add addict address adjust"
341 "baby bachelor bacon badge bag balance balcony ball bamboo banana banner bar barely bargain barrel base basic"
342 "basket battle beach bean beauty because become beef before begin behave behind"
343 "cabbage cabin cable cactus cage cake call calm camera camp can canal cancel candy cannon canoe canvas canyon"
344 "capable capital captain car carbon card cargo carpet carry cart case"
345 "daisy damage damp dance danger daring dash daughter dawn day deal debate debris decade december decide decline"
346 "decorate decrease deer defense define defy degree delay deliver demand demise denial";
347
348#define PUSH_BUNDLE_SIZE_TEST 184
349
350static void
352{
353 i = 0;
354 res = r0;
355 struct multi_context *m = *state;
356 const unsigned long cid = 0;
357 assert_int_equal(send_push_update(m, &cid, msg0, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
358}
359static void
361{
362 i = 0;
363 res = r1;
364 struct multi_context *m = *state;
365 const unsigned long cid = 0;
366 assert_int_equal(send_push_update(m, &cid, msg1, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
367}
368
369static void
371{
372 i = 0;
373 res = NULL;
374 struct multi_context *m = *state;
375 const unsigned long cid = 0;
376 assert_int_equal(send_push_update(m, &cid, msg2, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), -EINVAL);
377}
378
379static void
381{
382 i = 0;
383 res = r3;
384 struct multi_context *m = *state;
385 const unsigned long cid = 0;
386 assert_int_equal(send_push_update(m, &cid, msg3, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
387}
388
389static void
391{
392 i = 0;
393 res = r4;
394 struct multi_context *m = *state;
395 const unsigned long cid = 0;
396 assert_int_equal(send_push_update(m, &cid, msg4, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
397}
398
399static void
401{
402 i = 0;
403 res = r5;
404 struct multi_context *m = *state;
405 const unsigned long cid = 0;
406 assert_int_equal(send_push_update(m, &cid, msg5, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
407}
408
409static void
411{
412 i = 0;
413 res = r6;
414 struct multi_context *m = *state;
415 const unsigned long cid = 0;
416 assert_int_equal(send_push_update(m, &cid, msg6, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
417}
418
419static void
421{
422 i = 0;
423 res = r7;
424 struct multi_context *m = *state;
425 const unsigned long cid = 0;
426 assert_int_equal(send_push_update(m, &cid, msg7, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
427}
428
429static void
431{
432 i = 0;
433 res = r8;
434 struct multi_context *m = *state;
435 const unsigned long cid = 0;
436 assert_int_equal(send_push_update(m, &cid, msg8, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
437}
438
439static void
441{
442 i = 0;
443 res = r9;
444 struct multi_context *m = *state;
445 const unsigned long cid = 0;
446 assert_int_equal(send_push_update(m, &cid, msg9, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), 1);
447}
448
449static void
451{
452 i = 0;
453 res = NULL;
454 struct multi_context *m = *state;
455 const unsigned long cid = 0;
456 assert_int_equal(send_push_update(m, &cid, msg10, UPT_BY_CID, PUSH_BUNDLE_SIZE_TEST), -EINVAL);
457}
458
459#undef PUSH_BUNDLE_SIZE_TEST
460
461static int
462setup2(void **state)
463{
464 struct multi_context *m = calloc(1, sizeof(struct multi_context));
465 m->instances = calloc(1, sizeof(struct multi_instance *));
466 struct multi_instance *mi = calloc(1, sizeof(struct multi_instance));
467 *(m->instances) = mi;
468 *state = m;
469 return 0;
470}
471
472static int
473teardown2(void **state)
474{
475 struct multi_context *m = *state;
476 free(*(m->instances));
477 free(m->instances);
478 free(m);
479 return 0;
480}
481#endif /* ifdef ENABLE_MANAGEMENT */
482
483static int
484setup(void **state)
485{
486 struct context *c = calloc(1, sizeof(struct context));
487 c->options.pull = true;
488 c->options.route_nopull = false;
489 *state = c;
490 return 0;
491}
492
493static int
494teardown(void **state)
495{
496 struct context *c = *state;
497 free(c);
498 return 0;
499}
500
501int
502main(void)
503{
504 const struct CMUnitTest tests[] = {
505 cmocka_unit_test_setup_teardown(test_incoming_push_message_basic, setup, teardown),
506 cmocka_unit_test_setup_teardown(test_incoming_push_message_error1, setup, teardown),
507 cmocka_unit_test_setup_teardown(test_incoming_push_message_error2, setup, teardown),
508 cmocka_unit_test_setup_teardown(test_incoming_push_message_not_updatable_option, setup,
509 teardown),
510 cmocka_unit_test_setup_teardown(test_incoming_push_message_1, setup, teardown),
511 cmocka_unit_test_setup_teardown(test_incoming_push_message_bad_format, setup, teardown),
512 cmocka_unit_test_setup_teardown(test_incoming_push_message_mix, setup, teardown),
513 cmocka_unit_test_setup_teardown(test_incoming_push_message_mix2, setup, teardown),
514#ifdef ENABLE_MANAGEMENT
515 cmocka_unit_test_setup_teardown(test_send_push_msg0, setup2, teardown2),
516 cmocka_unit_test_setup_teardown(test_send_push_msg1, setup2, teardown2),
517 cmocka_unit_test_setup_teardown(test_send_push_msg2, setup2, teardown2),
518 cmocka_unit_test_setup_teardown(test_send_push_msg3, setup2, teardown2),
519 cmocka_unit_test_setup_teardown(test_send_push_msg4, setup2, teardown2),
520 cmocka_unit_test_setup_teardown(test_send_push_msg5, setup2, teardown2),
521 cmocka_unit_test_setup_teardown(test_send_push_msg6, setup2, teardown2),
522 cmocka_unit_test_setup_teardown(test_send_push_msg7, setup2, teardown2),
523 cmocka_unit_test_setup_teardown(test_send_push_msg8, setup2, teardown2),
524 cmocka_unit_test_setup_teardown(test_send_push_msg9, setup2, teardown2),
525 cmocka_unit_test_setup_teardown(test_send_push_msg10, setup2, teardown2)
526#endif
527 };
528
529 return cmocka_run_group_tests(tests, NULL, NULL);
530}
bool buf_string_compare_advance(struct buffer *src, const char *match)
Definition buffer.c:789
void free_buf(struct buffer *buf)
Definition buffer.c:184
struct buffer alloc_buf(size_t size)
Definition buffer.c:63
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Definition buffer.c:825
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition buffer.h:660
Header file for server-mode related structures and functions.
#define msg(flags,...)
Definition error.h:150
#define M_WARN
Definition error.h:90
#define OPT_P_UP
Definition options.h:733
#define OPT_P_NCP
Negotiable crypto parameters.
Definition options.h:744
#define OPT_P_ECHO
Definition options.h:752
#define OPT_P_EXPLICIT_NOTIFY
Definition options.h:751
#define OPT_P_SHAPER
Definition options.h:738
#define OPT_P_SOCKFLAGS
Definition options.h:758
#define OPT_P_MESSAGES
Definition options.h:743
#define OPT_P_SETENV
Definition options.h:737
#define OPT_P_SOCKBUF
Definition options.h:757
#define OPTION_PARM_SIZE
Definition options.h:56
#define OPT_P_TIMER
Definition options.h:739
#define OPT_P_DHCPDNS
Definition options.h:735
#define OPT_P_PULL_MODE
Definition options.h:755
#define OPT_P_PUSH_MTU
Definition options.h:762
#define OPT_P_PERSIST
Definition options.h:740
#define OPT_P_COMP
Definition options.h:742
#define OPT_P_ROUTE_EXTRAS
Definition options.h:754
#define OPT_P_PEER_ID
Definition options.h:760
#define OPT_P_ROUTE
Definition options.h:734
bool check_push_update_option_flags(char *line, int *i, unsigned int *flags)
Checks the formatting and validity of options inside push-update messages.
bool apply_pull_filter(const struct options *o, char *line)
Filter an option line by all pull filters.
@ UPT_BY_CID
Definition push.h:49
#define PUSH_MSG_REQUEST
Definition push.h:29
int send_push_update(struct multi_context *m, const void *target, const char *msg, const push_update_type type, const int push_bundle_size)
A function to send a PUSH_UPDATE control message from server to client(s).
Definition push_util.c:187
#define PUSH_OPT_OPTIONAL
Definition push.h:42
#define PUSH_MSG_ERROR
Definition push.h:28
#define PUSH_MSG_REPLY
Definition push.h:30
#define PUSH_MSG_UPDATE
Definition push.h:35
#define push_update_cmd
Definition push.h:38
#define push_reply_cmd
Definition push.h:37
int process_incoming_push_update(struct context *c, unsigned int permission_mask, unsigned int *option_types_found, struct buffer *buf, bool msg_sender)
Handles the receiving of a push-update message and applies updates to the specified options.
Definition push_util.c:13
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Contains all state information for one tunnel.
Definition openvpn.h:474
struct options options
Options loaded from command line or configuration file.
Definition openvpn.h:475
Main OpenVPN server state structure.
Definition multi.h:164
struct multi_instance ** instances
Array of multi_instances.
Definition multi.h:165
Server-mode state structure for one single VPN tunnel.
Definition multi.h:103
bool route_nopull
Definition options.h:440
bool pull
Definition options.h:559
struct pull_filter_list * pull_filter_list
Definition options.h:717
Security parameter state for a single VPN tunnel.
Definition ssl_common.h:612
struct env_set * es
bool options_postprocess_pull(struct options *options, struct env_set *es)
const char * msg2
static void test_send_push_msg2(void **state)
const char * msg10
static int teardown(void **state)
char * r4[]
static void test_send_push_msg9(void **state)
void throw_signal_soft(const int signum, const char *signal_text)
Throw a soft global signal.
static void test_send_push_msg4(void **state)
const char * msg1
static void test_send_push_msg1(void **state)
bool mroute_extract_openvpn_sockaddr(struct mroute_addr *addr, const struct openvpn_sockaddr *osaddr, bool use_port)
const char * msg8
static void test_send_push_msg3(void **state)
char * r9[]
static void test_send_push_msg0(void **state)
const char * msg6
static void test_send_push_msg8(void **state)
struct multi_instance * lookup_by_cid(struct multi_context *m, const unsigned long cid)
static int teardown2(void **state)
char * r5[]
const char * msg0
static void test_incoming_push_message_bad_format(void **state)
char ** res
void update_vhash(struct multi_context *m, struct multi_instance *mi, const char *old_ip, const char *old_ipv6)
Update the vhash with new IP/IPv6 addresses in the multi_context when a push-update message containin...
char * r3[]
static void test_send_push_msg6(void **state)
static void test_send_push_msg7(void **state)
const char * msg4
bool send_control_channel_string(struct context *c, const char *str, int msglevel)
int main(void)
const char * msg5
static void test_incoming_push_message_error2(void **state)
static void test_send_push_msg5(void **state)
const char * msg7
static int setup2(void **state)
bool apply_push_options(struct context *c, struct options *options, struct buffer *buf, unsigned int permission_mask, unsigned int *option_types_found, struct env_set *es, bool is_update)
static void test_send_push_msg10(void **state)
char * r6[]
static void test_incoming_push_message_mix(void **state)
static int setup(void **state)
static void test_incoming_push_message_basic(void **state)
static void test_incoming_push_message_1(void **state)
static void test_incoming_push_message_error1(void **state)
static void test_incoming_push_message_mix2(void **state)
const char * msg9
static void test_incoming_push_message_not_updatable_option(void **state)
#define PUSH_BUNDLE_SIZE_TEST
unsigned int pull_permission_mask(const struct context *c)
int process_incoming_push_msg(struct context *c, const struct buffer *buffer, bool honor_received_options, unsigned int permission_mask, unsigned int *option_types_found)
char * r8[]
const char * tls_common_name(const struct tls_multi *multi, const bool null)
Returns the common name field for the given tunnel.
char * r1[]
char * r0[]
char * r7[]
const char * msg3