]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-server: refuse invalid hostname in request
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 11 Mar 2024 16:47:17 +0000 (01:47 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 11 Mar 2024 16:57:17 +0000 (01:57 +0900)
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.

src/libsystemd-network/dhcp-option.c
src/libsystemd-network/dhcp-option.h
src/libsystemd-network/sd-dhcp-server.c

index 4a6fa462f12f88963da60972134af3d614eac662..e4ba77ae29648bd05db1477d8e54c43b99be024c 100644 (file)
@@ -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;
index 425f5b50162c1a28ed736973cf023a5a07d90bfa..aaa8f847b1a0036153010cabb01f8e694e860e17 100644 (file)
@@ -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);
index d59bf430d7ace6f9e174bbb0ec8438200b60997e..dd4cbd3064b581eed123fa16c2756fb9457d6e02 100644 (file)
@@ -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;