With this option, the server can remove individual options from the
set pushed to a client (call from --client-config-dir file, or from
--client-connect script or plugin). Options are removed at parse
time, so it is possible to do stuff like:
push-remove route-ipv6
push "route-ipv6 fd00::/8"
to first remove all IPv6 route options set so far, then add something
specific (what "push-reset" does to all the options).
Arguments to push-remove are strncmp()'ed to option string, so partial
matches like
push-remove "route-ipv6 2001:"
are possible ("remove all IPv6 routes starting with 2001:").
Implementation of remove_iroutes_from_push_route_list() had to be changed
slightly to stop it from re-enabling all disabled options again.
v2: documentation (Changes.rst, doc/openvpn.8)
remove surplus gc_arena
implement filtering of "ifconfig-ipv6"
v3: correct quoting in commit message
only handle a single argument per push-remove statement - if multiple
options are to be removed, just use multiple push-remove statements
Trac #29, #614
Signed-off-by: Gert Doering <gert@greenie.muc.de>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <1463393584-8318-1-git-send-email-gert@greenie.muc.de>
URL: http://article.gmane.org/gmane.network.openvpn.devel/11665
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -5,6 +5,10 @@ Version 2.4.0 |
5 | 5 |
New features |
6 | 6 |
------------ |
7 | 7 |
|
8 |
+push-remove |
|
9 |
+ new option to remove options on a per-client basis from the "push" list |
|
10 |
+ (more fine-grained than "push-reset") |
|
11 |
+ |
|
8 | 12 |
keying-material-exporter |
9 | 13 |
Keying Material Exporter [RFC-5705] allow additional keying material to be |
10 | 14 |
derived from existing TLS channel. |
... | ... |
@@ -2965,6 +2965,39 @@ as with a |
2965 | 2965 |
configuration file. This option will ignore |
2966 | 2966 |
.B \-\-push |
2967 | 2967 |
options at the global config file level. |
2968 |
+.\"********************************************************* |
|
2969 |
+.TP |
|
2970 |
+.B \-\-push\-remove opt |
|
2971 |
+selectively remove all |
|
2972 |
+.B \-\-push |
|
2973 |
+options matching "opt" from the option list for a client. "opt" is matched |
|
2974 |
+as a substring against the whole option string to-be-pushed to the client, so |
|
2975 |
+.B \-\-push\-remove route |
|
2976 |
+would remove all |
|
2977 |
+.B \-\-push route ... |
|
2978 |
+and |
|
2979 |
+.B \-\-push route-ipv6 ... |
|
2980 |
+statements, while |
|
2981 |
+.B \-\-push\-remove 'route-ipv6 2001:' |
|
2982 |
+would only remove IPv6 routes for 2001:... networks. |
|
2983 |
+ |
|
2984 |
+.B \-\-push\-remove |
|
2985 |
+can only be used in a client-specific context, like in a |
|
2986 |
+.B \-\-client\-config\-dir |
|
2987 |
+file, or |
|
2988 |
+.B \-\-client\-connect |
|
2989 |
+script or plugin -- similar to |
|
2990 |
+.B \-\-push\-reset, |
|
2991 |
+just more selective. |
|
2992 |
+ |
|
2993 |
+NOTE: to |
|
2994 |
+.I change |
|
2995 |
+an option, |
|
2996 |
+.B \-\-push\-remove |
|
2997 |
+can be used to first remove the old value, and then add a new |
|
2998 |
+.B \-\-push |
|
2999 |
+option with the new value. |
|
3000 |
+.\"********************************************************* |
|
2968 | 3001 |
.TP |
2969 | 3002 |
.B \-\-push\-peer\-info |
2970 | 3003 |
Push additional information about the client to server. The additional information |
... | ... |
@@ -3289,7 +3322,7 @@ without needing to restart the server. |
3289 | 3289 |
|
3290 | 3290 |
The following |
3291 | 3291 |
options are legal in a client-specific context: |
3292 |
-.B \-\-push, \-\-push\-reset, \-\-iroute, \-\-ifconfig\-push, |
|
3292 |
+.B \-\-push, \-\-push\-reset, \-\-push\-remove, \-\-iroute, \-\-ifconfig\-push, |
|
3293 | 3293 |
and |
3294 | 3294 |
.B \-\-config. |
3295 | 3295 |
.\"********************************************************* |
... | ... |
@@ -5582,6 +5582,11 @@ add_option (struct options *options, |
5582 | 5582 |
VERIFY_PERMISSION (OPT_P_INSTANCE); |
5583 | 5583 |
push_reset (options); |
5584 | 5584 |
} |
5585 |
+ else if (streq (p[0], "push-remove") && p[1] && !p[2]) |
|
5586 |
+ { |
|
5587 |
+ VERIFY_PERMISSION (OPT_P_INSTANCE); |
|
5588 |
+ push_remove_option (options,p[1]); |
|
5589 |
+ } |
|
5585 | 5590 |
else if (streq (p[0], "ifconfig-pool") && p[1] && p[2] && !p[4]) |
5586 | 5591 |
{ |
5587 | 5592 |
const int lev = M_WARN; |
... | ... |
@@ -5930,6 +5935,7 @@ add_option (struct options *options, |
5930 | 5930 |
options->push_ifconfig_ipv6_local = local; |
5931 | 5931 |
options->push_ifconfig_ipv6_netbits = netbits; |
5932 | 5932 |
options->push_ifconfig_ipv6_remote = remote; |
5933 |
+ options->push_ifconfig_ipv6_blocked = false; |
|
5933 | 5934 |
} |
5934 | 5935 |
else if (streq (p[0], "disable") && !p[1]) |
5935 | 5936 |
{ |
... | ... |
@@ -432,6 +432,7 @@ struct options |
432 | 432 |
struct in6_addr push_ifconfig_ipv6_local; /* IPv6 */ |
433 | 433 |
int push_ifconfig_ipv6_netbits; /* IPv6 */ |
434 | 434 |
struct in6_addr push_ifconfig_ipv6_remote; /* IPv6 */ |
435 |
+ bool push_ifconfig_ipv6_blocked; /* IPv6 */ |
|
435 | 436 |
bool enable_c2c; |
436 | 437 |
bool duplicate_cn; |
437 | 438 |
int cf_max; |
... | ... |
@@ -322,7 +322,8 @@ send_push_reply (struct context *c) |
322 | 322 |
|
323 | 323 |
buf_printf (&buf, "%s", cmd); |
324 | 324 |
|
325 |
- if ( c->c2.push_ifconfig_ipv6_defined ) |
|
325 |
+ if ( c->c2.push_ifconfig_ipv6_defined && |
|
326 |
+ !c->options.push_ifconfig_ipv6_blocked ) |
|
326 | 327 |
{ |
327 | 328 |
/* IPv6 is put into buffer first, could be lengthy */ |
328 | 329 |
buf_printf( &buf, ",ifconfig-ipv6 %s/%d %s", |
... | ... |
@@ -483,6 +484,37 @@ push_reset (struct options *o) |
483 | 483 |
{ |
484 | 484 |
CLEAR (o->push_list); |
485 | 485 |
} |
486 |
+ |
|
487 |
+void |
|
488 |
+push_remove_option (struct options *o, const char *p) |
|
489 |
+{ |
|
490 |
+ msg( D_PUSH, "PUSH_REMOVE '%s'", p ); |
|
491 |
+ |
|
492 |
+ /* ifconfig-ipv6 is special, as not part of the push list */ |
|
493 |
+ if ( streq( p, "ifconfig-ipv6" )) |
|
494 |
+ { |
|
495 |
+ o->push_ifconfig_ipv6_blocked = true; |
|
496 |
+ return; |
|
497 |
+ } |
|
498 |
+ |
|
499 |
+ if (o && o->push_list.head ) |
|
500 |
+ { |
|
501 |
+ struct push_entry *e = o->push_list.head; |
|
502 |
+ |
|
503 |
+ /* cycle through the push list */ |
|
504 |
+ while (e) |
|
505 |
+ { |
|
506 |
+ if ( e->enable && |
|
507 |
+ strncmp( e->option, p, strlen(p) ) == 0 ) |
|
508 |
+ { |
|
509 |
+ msg (D_PUSH, "PUSH_REMOVE removing: '%s'", e->option); |
|
510 |
+ e->enable = false; |
|
511 |
+ } |
|
512 |
+ |
|
513 |
+ e = e->next; |
|
514 |
+ } |
|
515 |
+ } |
|
516 |
+} |
|
486 | 517 |
#endif |
487 | 518 |
|
488 | 519 |
#if P2MP_SERVER |
... | ... |
@@ -613,7 +645,8 @@ remove_iroutes_from_push_route_list (struct options *o) |
613 | 613 |
|
614 | 614 |
/* parse the push item */ |
615 | 615 |
CLEAR (p); |
616 |
- if (parse_line (e->option, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc)) |
|
616 |
+ if ( e->enable && |
|
617 |
+ parse_line (e->option, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc)) |
|
617 | 618 |
{ |
618 | 619 |
/* is the push item a route directive? */ |
619 | 620 |
if (p[0] && !strcmp (p[0], "route") && !p[3]) |
... | ... |
@@ -639,12 +672,12 @@ remove_iroutes_from_push_route_list (struct options *o) |
639 | 639 |
} |
640 | 640 |
} |
641 | 641 |
} |
642 |
- } |
|
643 | 642 |
|
644 |
- /* should we copy the push item? */ |
|
645 |
- e->enable = enable; |
|
646 |
- if (!enable) |
|
647 |
- msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", e->option); |
|
643 |
+ /* should we copy the push item? */ |
|
644 |
+ e->enable = enable; |
|
645 |
+ if (!enable) |
|
646 |
+ msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", e->option); |
|
647 |
+ } |
|
648 | 648 |
|
649 | 649 |
e = e->next; |
650 | 650 |
} |
... | ... |
@@ -61,6 +61,7 @@ void push_option (struct options *o, const char *opt, int msglevel); |
61 | 61 |
void push_options (struct options *o, char **p, int msglevel, struct gc_arena *gc); |
62 | 62 |
|
63 | 63 |
void push_reset (struct options *o); |
64 |
+void push_remove_option (struct options *o, const char *p); |
|
64 | 65 |
|
65 | 66 |
void remove_iroutes_from_push_route_list (struct options *o); |
66 | 67 |
|