From 05a33ce2a522e404d99b0815f4dca8eb914bd642 Mon Sep 17 00:00:00 2001
From: chantra <chantra@debuntu.org>
Date: Thu, 29 Jul 2010 10:14:26 +0200
Subject: [PATCH] Make some push options not resetable by ccd config
Fixes bug ticket 29
<https://community.openvpn.net/openvpn/ticket/29>
When client configuration has a 'push-reset' option,
non-immutable global options will not be pushed to client.
Only options added after the *last* push-reset will be set
immutable.
This way, if push-reset is given in ccd files and plugin
returned list, only the configuration options from the plugin
will be set immutable.
Signed-off-by: chantra <chantra@debuntu.org>
---
helper.c | 5 ++++
multi.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
options.c | 3 +-
options.h | 1 +
push.c | 3 +-
pushlist.h | 1 +
6 files changed, 76 insertions(+), 3 deletions(-)
diff --git a/helper.c b/helper.c
index a9d7fd9..44723b4 100644
a
|
b
|
helper_client_server (struct options *o) |
256 | 256 | o->ifconfig_pool_netmask = o->server_netmask; |
257 | 257 | |
258 | 258 | push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE); |
| 259 | o->push_list.tail->immutable = true; |
259 | 260 | } |
260 | 261 | else |
261 | 262 | ASSERT (0); |
262 | 263 | |
263 | 264 | push_option (o, print_opt_topology (topology, &o->gc), M_USAGE); |
| 265 | o->push_list.tail->immutable = true; |
264 | 266 | } |
265 | 267 | else if (dev == DEV_TYPE_TAP) |
266 | 268 | { |
… |
… |
helper_client_server (struct options *o) |
283 | 285 | o->ifconfig_pool_netmask = o->server_netmask; |
284 | 286 | |
285 | 287 | push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE); |
| 288 | o->push_list.tail->immutable = true; |
286 | 289 | } |
287 | 290 | else |
288 | 291 | { |
… |
… |
helper_client_server (struct options *o) |
355 | 358 | ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end); |
356 | 359 | o->ifconfig_pool_netmask = o->server_bridge_netmask; |
357 | 360 | push_option (o, print_opt_route_gateway (o->server_bridge_ip, &o->gc), M_USAGE); |
| 361 | o->push_list.tail->immutable = true; |
358 | 362 | } |
359 | 363 | else if (o->server_bridge_proxy_dhcp && !(o->server_flags & SF_NO_PUSH_ROUTE_GATEWAY)) |
360 | 364 | { |
361 | 365 | push_option (o, print_opt_route_gateway_dhcp (&o->gc), M_USAGE); |
| 366 | o->push_list.tail->immutable = true; |
362 | 367 | } |
363 | 368 | } |
364 | 369 | else |
diff --git a/multi.c b/multi.c
index dc26a02..899a345 100644
a
|
b
|
multi_set_virtual_addr_env (struct multi_context *m, struct multi_instance *mi) |
1283 | 1283 | } |
1284 | 1284 | |
1285 | 1285 | /* |
| 1286 | * Set list entry immutable flag to immutable |
| 1287 | * until end of list |
| 1288 | */ |
| 1289 | static void |
| 1290 | multi_client_connect_post_set_immutable (struct push_entry *e, |
| 1291 | bool immutable) |
| 1292 | { |
| 1293 | while( e ){ |
| 1294 | e->immutable = immutable; |
| 1295 | e = e->next; |
| 1296 | } |
| 1297 | } |
| 1298 | |
| 1299 | /* |
1286 | 1300 | * Called after client-connect script is called |
1287 | 1301 | */ |
1288 | 1302 | static void |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1442 | 1456 | { |
1443 | 1457 | struct gc_arena gc = gc_new (); |
1444 | 1458 | unsigned int option_types_found = 0; |
| 1459 | struct push_entry *immutable_from_option = NULL, *last_option = NULL; |
| 1460 | bool push_reset = false; |
1445 | 1461 | |
1446 | 1462 | const unsigned int option_permissions_mask = |
1447 | 1463 | OPT_P_INSTANCE |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1487 | 1503 | /* try common-name file */ |
1488 | 1504 | if (test_file (ccd_file)) |
1489 | 1505 | { |
| 1506 | last_option = mi->context.options.push_list.tail; |
1490 | 1507 | options_server_import (&mi->context.options, |
1491 | 1508 | ccd_file, |
1492 | 1509 | D_IMPORT_ERRORS|M_OPTERR, |
1493 | 1510 | option_permissions_mask, |
1494 | 1511 | &option_types_found, |
1495 | 1512 | mi->context.c2.es); |
| 1513 | if (mi->context.options.push_reset){ |
| 1514 | immutable_from_option = last_option; |
| 1515 | push_reset = true; |
| 1516 | mi->context.options.push_reset = false; |
| 1517 | } |
1496 | 1518 | } |
1497 | 1519 | else /* try default file */ |
1498 | 1520 | { |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1502 | 1524 | |
1503 | 1525 | if (test_file (ccd_file)) |
1504 | 1526 | { |
| 1527 | last_option = mi->context.options.push_list.tail; |
1505 | 1528 | options_server_import (&mi->context.options, |
1506 | 1529 | ccd_file, |
1507 | 1530 | D_IMPORT_ERRORS|M_OPTERR, |
1508 | 1531 | option_permissions_mask, |
1509 | 1532 | &option_types_found, |
1510 | 1533 | mi->context.c2.es); |
| 1534 | |
| 1535 | if (mi->context.options.push_reset){ |
| 1536 | immutable_from_option = last_option; |
| 1537 | push_reset = true; |
| 1538 | mi->context.options.push_reset = false; |
| 1539 | } |
1511 | 1540 | } |
1512 | 1541 | } |
1513 | 1542 | } |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1545 | 1574 | } |
1546 | 1575 | else |
1547 | 1576 | { |
| 1577 | last_option = mi->context.options.push_list.tail; |
1548 | 1578 | multi_client_connect_post (m, mi, dc_file, option_permissions_mask, &option_types_found); |
| 1579 | if (mi->context.options.push_reset){ |
| 1580 | immutable_from_option = last_option; |
| 1581 | push_reset = true; |
| 1582 | mi->context.options.push_reset = false; |
| 1583 | } |
| 1584 | |
1549 | 1585 | ++cc_succeeded_count; |
1550 | 1586 | } |
1551 | 1587 | script_depr_failed: |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1566 | 1602 | } |
1567 | 1603 | else |
1568 | 1604 | { |
| 1605 | last_option = mi->context.options.push_list.tail; |
1569 | 1606 | multi_client_connect_post_plugin (m, mi, &pr, option_permissions_mask, &option_types_found); |
1570 | 1607 | ++cc_succeeded_count; |
| 1608 | if (mi->context.options.push_reset){ |
| 1609 | immutable_from_option = last_option; |
| 1610 | push_reset = true; |
| 1611 | mi->context.options.push_reset = false; |
| 1612 | } |
| 1613 | |
1571 | 1614 | } |
1572 | 1615 | |
1573 | 1616 | plugin_return_free (&pr); |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1596 | 1639 | |
1597 | 1640 | if (openvpn_execve_check (&argv, mi->context.c2.es, S_SCRIPT, "client-connect command failed")) |
1598 | 1641 | { |
| 1642 | last_option = mi->context.options.push_list.tail; |
1599 | 1643 | multi_client_connect_post (m, mi, dc_file, option_permissions_mask, &option_types_found); |
1600 | 1644 | ++cc_succeeded_count; |
| 1645 | if (mi->context.options.push_reset){ |
| 1646 | immutable_from_option = last_option; |
| 1647 | push_reset = true; |
| 1648 | mi->context.options.push_reset = false; |
| 1649 | } |
1601 | 1650 | } |
1602 | 1651 | else |
1603 | 1652 | cc_succeeded = false; |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1611 | 1660 | #ifdef MANAGEMENT_DEF_AUTH |
1612 | 1661 | if (cc_succeeded && mi->cc_config) |
1613 | 1662 | { |
| 1663 | last_option = mi->context.options.push_list.tail; |
1614 | 1664 | multi_client_connect_mda (m, mi, mi->cc_config, option_permissions_mask, &option_types_found); |
1615 | 1665 | ++cc_succeeded_count; |
| 1666 | if (mi->context.options.push_reset){ |
| 1667 | immutable_from_option = last_option; |
| 1668 | push_reset = true; |
| 1669 | mi->context.options.push_reset = false; |
| 1670 | } |
1616 | 1671 | } |
1617 | 1672 | #endif |
1618 | 1673 | |
… |
… |
multi_connection_established (struct multi_context *m, struct multi_instance *mi |
1625 | 1680 | msg (D_MULTI_ERRORS, "MULTI: client has been rejected due to 'disable' directive"); |
1626 | 1681 | cc_succeeded = false; |
1627 | 1682 | } |
1628 | | |
| 1683 | /* |
| 1684 | * Set option push_reset to true if push-reset option |
| 1685 | * was ever encountered, and set to immutable |
| 1686 | * options added since last push-reset |
| 1687 | */ |
| 1688 | mi->context.options.push_reset = push_reset; |
| 1689 | if( push_reset ){ |
| 1690 | multi_client_connect_post_set_immutable( |
| 1691 | immutable_from_option ? immutable_from_option->next : mi->context.options.push_list.head, true); |
| 1692 | } |
1629 | 1693 | if (cc_succeeded) |
1630 | 1694 | { |
1631 | 1695 | /* |
diff --git a/options.c b/options.c
index b78158e..20c5f60 100644
a
|
b
|
init_options (struct options *o, const bool init_gc) |
691 | 691 | o->route_delay_window = 30; |
692 | 692 | o->max_routes = MAX_ROUTES_DEFAULT; |
693 | 693 | o->resolve_retry_seconds = RESOLV_RETRY_INFINITE; |
| 694 | o->push_reset = false; |
694 | 695 | #ifdef ENABLE_OCC |
695 | 696 | o->occ = true; |
696 | 697 | #endif |
… |
… |
add_option (struct options *options, |
4789 | 4790 | else if (streq (p[0], "push-reset")) |
4790 | 4791 | { |
4791 | 4792 | VERIFY_PERMISSION (OPT_P_INSTANCE); |
4792 | | push_reset (options); |
| 4793 | options->push_reset = true; |
4793 | 4794 | } |
4794 | 4795 | else if (streq (p[0], "ifconfig-pool") && p[1] && p[2]) |
4795 | 4796 | { |
diff --git a/options.h b/options.h
index 240f3bb..4b1597f 100644
a
|
b
|
struct options |
378 | 378 | in_addr_t server_bridge_pool_end; |
379 | 379 | |
380 | 380 | struct push_list push_list; |
| 381 | bool push_reset; |
381 | 382 | bool ifconfig_pool_defined; |
382 | 383 | in_addr_t ifconfig_pool_start; |
383 | 384 | in_addr_t ifconfig_pool_end; |
diff --git a/push.c b/push.c
index 1320bec..9d994a5 100644
a
|
b
|
send_push_reply (struct context *c) |
183 | 183 | |
184 | 184 | while (e) |
185 | 185 | { |
186 | | if (e->enable) |
| 186 | if (e->enable && (!c->options.push_reset || e->immutable)) |
187 | 187 | { |
188 | 188 | const int l = strlen (e->option); |
189 | 189 | if (BLEN (&buf) + l >= safe_cap) |
… |
… |
clone_push_list (struct options *o) |
290 | 290 | while (e) |
291 | 291 | { |
292 | 292 | push_option_ex (o, string_alloc (e->option, &o->gc), true, M_FATAL); |
| 293 | o->push_list.tail->immutable = e->immutable; |
293 | 294 | e = e->next; |
294 | 295 | } |
295 | 296 | } |
diff --git a/pushlist.h b/pushlist.h
index b252676..11356dd 100644
a
|
b
|
|
30 | 30 | struct push_entry { |
31 | 31 | struct push_entry *next; |
32 | 32 | bool enable; |
| 33 | bool immutable; |
33 | 34 | const char *option; |
34 | 35 | }; |
35 | 36 | |