summaryrefslogtreecommitdiffstats
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-03-11 17:47:17 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2024-03-11 17:57:17 +0100
commit5a2f378362f2b16f8d837aec4c44532eed737a03 (patch)
treeb38ce49ac8624416ae7d929ce0ae73f8632273a9 /src/libsystemd-network
parentdhcp-option: refuse control and non-UTF8 characters in string option (diff)
downloadsystemd-5a2f378362f2b16f8d837aec4c44532eed737a03.tar.xz
systemd-5a2f378362f2b16f8d837aec4c44532eed737a03.zip
sd-dhcp-server: refuse invalid hostname in request
Currently, the received hostname is not used for assigning an address to the host, or options in the subsequent reply message. But, the parsed hostname is exposed through DBus, and possibly Varlink in the future. Let's ignore spurious hostname.
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp-option.c31
-rw-r--r--src/libsystemd-network/dhcp-option.h1
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c14
3 files changed, 40 insertions, 6 deletions
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 4a6fa462f1..e4ba77ae29 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -10,6 +10,8 @@
#include "alloc-util.h"
#include "dhcp-option.h"
#include "dhcp-server-internal.h"
+#include "dns-domain.h"
+#include "hostname-util.h"
#include "memory-util.h"
#include "ordered-set.h"
#include "strv.h"
@@ -420,6 +422,35 @@ int dhcp_option_parse_string(const uint8_t *option, size_t len, char **ret) {
return 0;
}
+int dhcp_option_parse_hostname(const uint8_t *option, size_t len, char **ret) {
+ _cleanup_free_ char *hostname = NULL;
+ int r;
+
+ assert(option);
+ assert(ret);
+
+ r = dhcp_option_parse_string(option, len, &hostname);
+ if (r < 0)
+ return r;
+
+ if (!hostname) {
+ *ret = NULL;
+ return 0;
+ }
+
+ if (!hostname_is_valid(hostname, 0))
+ return -EINVAL;
+
+ r = dns_name_is_valid(hostname);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EINVAL;
+
+ *ret = TAKE_PTR(hostname);
+ return 0;
+}
+
static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) {
if (!i)
return NULL;
diff --git a/src/libsystemd-network/dhcp-option.h b/src/libsystemd-network/dhcp-option.h
index 425f5b5016..aaa8f847b1 100644
--- a/src/libsystemd-network/dhcp-option.h
+++ b/src/libsystemd-network/dhcp-option.h
@@ -44,3 +44,4 @@ int dhcp_option_parse(
char **ret_error_message);
int dhcp_option_parse_string(const uint8_t *option, size_t len, char **ret);
+int dhcp_option_parse_hostname(const uint8_t *option, size_t len, char **ret);
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index d59bf430d7..dd4cbd3064 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -746,14 +746,16 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
req->agent_info_option = (uint8_t*)option - 2;
break;
- case SD_DHCP_OPTION_HOST_NAME:
- r = dhcp_option_parse_string(option, len, &req->hostname);
- if (r < 0) {
- log_debug_errno(r, "Failed to parse hostname, ignoring: %m");
- return 0;
- }
+ case SD_DHCP_OPTION_HOST_NAME: {
+ _cleanup_free_ char *p = NULL;
+ r = dhcp_option_parse_hostname(option, len, &p);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse hostname, ignoring: %m");
+ else
+ free_and_replace(req->hostname, p);
break;
+ }
case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
req->parameter_request_list = option;
req->parameter_request_list_len = len;