From 98ebef62c7fe240c261bc2a197b7baac231aab77 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Fri, 26 Jun 2020 03:28:52 +0000 Subject: [PATCH] DHCPv4: client add support for DHCP server allow list --- man/systemd.network.xml | 10 ++- src/network/networkd-dhcp4.c | 64 +++++++++++++++---- src/network/networkd-dhcp4.h | 2 +- src/network/networkd-network-gperf.gperf | 5 +- src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 + .../fuzz-network-parser/directives.network | 1 + 7 files changed, 67 insertions(+), 17 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 88f00bdca6..d08543c5fc 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1748,7 +1748,15 @@ DenyList= - A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are rejected. + A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are rejected. Note that + if AllowList= is configured then DenyList= is ignored. + + + + + AllowList= + + A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are accepted. diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 20dae6c19f..9a99c1e6f9 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1079,6 +1079,34 @@ static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) { return false; } +static int dhcp_server_is_allow_listed(Link *link, sd_dhcp_client *client) { + sd_dhcp_lease *lease; + struct in_addr addr; + int r; + + assert(link); + assert(link->network); + assert(client); + + r = sd_dhcp_client_get_lease(client, &lease); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get DHCP lease: %m"); + + r = sd_dhcp_lease_get_server_identifier(lease, &addr); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m"); + + if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) { + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in allow-listed ip addresses, accepting offer", + ADDRESS_FMT_VAL(addr))); + return true; + } + + return false; +} + static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) { Link *link = userdata; int r; @@ -1163,12 +1191,19 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) { } break; case SD_DHCP_CLIENT_EVENT_SELECTING: - r = dhcp_server_is_deny_listed(link, client); - if (r < 0) - return r; - if (r != 0) - return -ENOMSG; - + if (!set_isempty(link->network->dhcp_allow_listed_ip)) { + r = dhcp_server_is_allow_listed(link, client); + if (r < 0) + return r; + if (r == 0) + return -ENOMSG; + } else { + r = dhcp_server_is_deny_listed(link, client); + if (r < 0) + return r; + if (r != 0) + return -ENOMSG; + } break; default: if (event < 0) @@ -1551,7 +1586,7 @@ int config_parse_dhcp_max_attempts( return 0; } -int config_parse_dhcp_deny_listed_ip_address( +int config_parse_dhcp_acl_ip_address( const char *unit, const char *filename, unsigned line, @@ -1564,6 +1599,7 @@ int config_parse_dhcp_deny_listed_ip_address( void *userdata) { Network *network = data; + Set **acl; int r; assert(filename); @@ -1571,8 +1607,10 @@ int config_parse_dhcp_deny_listed_ip_address( assert(rvalue); assert(data); + acl = STR_IN_SET(lvalue, "DenyList", "BlackList") ? &network->dhcp_deny_listed_ip : &network->dhcp_allow_listed_ip; + if (isempty(rvalue)) { - network->dhcp_deny_listed_ip = set_free(network->dhcp_deny_listed_ip); + *acl = set_free(*acl); return 0; } @@ -1583,8 +1621,8 @@ int config_parse_dhcp_deny_listed_ip_address( r = extract_first_word(&p, &n, NULL, 0); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse DHCP deny-listed IP address, ignoring assignment: %s", - rvalue); + "Failed to parse DHCP '%s=' IP address, ignoring assignment: %s", + lvalue, rvalue); return 0; } if (r == 0) @@ -1593,14 +1631,14 @@ int config_parse_dhcp_deny_listed_ip_address( r = in_addr_from_string(AF_INET, n, &ip); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, - "DHCP deny-listed IP address is invalid, ignoring assignment: %s", n); + "DHCP '%s=' IP address is invalid, ignoring assignment: %s", lvalue, n); continue; } - r = set_ensure_put(&network->dhcp_deny_listed_ip, NULL, UINT32_TO_PTR(ip.in.s_addr)); + r = set_ensure_put(acl, NULL, UINT32_TO_PTR(ip.in.s_addr)); if (r < 0) log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to store DHCP deny-listed IP address '%s', ignoring assignment: %m", n); + "Failed to store DHCP '%s=' IP address '%s', ignoring assignment: %m", lvalue, n); } return 0; diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 567ee724da..96ac696ce6 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -23,7 +23,7 @@ int dhcp4_set_client_identifier(Link *link); int dhcp4_set_promote_secondaries(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_deny_listed_ip_address); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 087358da11..6b471c51e9 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -197,8 +197,8 @@ DHCPv4.IAID, config_parse_iaid, DHCPv4.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release) DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline) -DHCPv4.DenyList, config_parse_dhcp_deny_listed_ip_address, 0, 0 -DHCPv4.BlackList, config_parse_dhcp_deny_listed_ip_address, 0, 0 +DHCPv4.DenyList, config_parse_dhcp_acl_ip_address, 0, 0 +DHCPv4.AllowList, config_parse_dhcp_acl_ip_address, 0, 0 DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, ip_service_type) DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options) DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options) @@ -414,6 +414,7 @@ TrivialLinkEqualizer.Handle, config_parse_qdisc_handle, TrivialLinkEqualizer.Id, config_parse_trivial_link_equalizer_id, QDISC_KIND_TEQL, 0 /* backwards compatibility: do not add new entries to this section */ Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) +DHCPv4.BlackList, config_parse_dhcp_acl_ip_address, 0, 0 DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) DHCP.UseDNS, config_parse_dhcp_use_dns, 0, 0 DHCP.UseNTP, config_parse_dhcp_use_ntp, 0, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 5316faeedb..22bd06a891 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -670,6 +670,7 @@ static Network *network_free(Network *network) { strv_free(network->dhcp_user_class); free(network->dhcp_hostname); set_free(network->dhcp_deny_listed_ip); + set_free(network->dhcp_allow_listed_ip); set_free(network->dhcp_request_options); set_free(network->dhcp6_request_options); free(network->mac); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 2ce555bfc5..424298248f 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -140,6 +140,7 @@ struct Network { DHCPUseDomains dhcp_use_domains; sd_ipv4acd *dhcp_acd; Set *dhcp_deny_listed_ip; + Set *dhcp_allow_listed_ip; Set *dhcp_request_options; OrderedHashmap *dhcp_client_send_options; OrderedHashmap *dhcp_client_send_vendor_options; diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 1754a1cd82..aa04c1192a 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -107,6 +107,7 @@ UseTimezone= RouteTable= DenyList= BlackList= +AllowList= RequestOptions= SendRelease= MaxAttempts=