summary refs log tree commit diff
path: root/src/core/dns
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2023-08-09 21:55:35 +0200
committerMichael Biebl <biebl@debian.org>2023-08-09 21:55:35 +0200
commit05e4a733f2141995181a551854d5df929f084adf (patch)
tree83bb937740a6667525ba0df046748ecaa829c269 /src/core/dns
parent14b0f3a9dc9ea90d60a3b057350fd4d637dc021a (diff)
New upstream version 1.44.0 upstream/1.44.0
Diffstat (limited to 'src/core/dns')
-rw-r--r--src/core/dns/nm-dns-dnsmasq.c1
-rw-r--r--src/core/dns/nm-dns-manager.c90
2 files changed, 78 insertions, 13 deletions
diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c
index 05aeff49..53e40f59 100644
--- a/src/core/dns/nm-dns-dnsmasq.c
+++ b/src/core/dns/nm-dns-dnsmasq.c
@@ -527,7 +527,6 @@ _gl_pid_spawn_next_step(void)
     argv[argv_idx++] = "--cache-size=400";
     argv[argv_idx++] = "--clear-on-reload";     /* clear cache when dns server changes */
     argv[argv_idx++] = "--conf-file=/dev/null"; /* avoid loading /etc/dnsmasq.conf */
-    argv[argv_idx++] = "--proxy-dnssec";        /* Allow DNSSEC to pass through */
     argv[argv_idx++] = "--enable-dbus=" DNSMASQ_DBUS_SERVICE;
 
     /* dnsmasq exits if the conf dir is not present */
diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c
index 6ee2e816..53564693 100644
--- a/src/core/dns/nm-dns-manager.c
+++ b/src/core/dns/nm-dns-manager.c
@@ -125,6 +125,9 @@ typedef struct {
 
     NMConfig *config;
 
+    NMDnsConfigIPData *best_ip_config_4;
+    NMDnsConfigIPData *best_ip_config_6;
+
     struct {
         guint64 ts;
         guint   num_restarts;
@@ -173,14 +176,46 @@ NM_DEFINE_SINGLETON_GETTER(NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER
 /*****************************************************************************/
 
 static gboolean
-domain_is_valid(const char *domain, gboolean check_public_suffix)
+domain_is_valid(const char *domain,
+                gboolean    reject_public_suffix,
+                gboolean    assume_any_tld_is_public)
 {
     if (*domain == '\0')
         return FALSE;
-#if WITH_LIBPSL
-    if (check_public_suffix && psl_is_public_suffix(psl_builtin(), domain))
-        return FALSE;
+
+    if (reject_public_suffix) {
+        int is_pub;
+
+#if !WITH_LIBPSL
+        /* Without libpsl, we cannot detect that the domain is a public suffix, we assume
+         * the domain is not and valid. */
+        is_pub = FALSE;
+#elif defined(PSL_TYPE_NO_STAR_RULE)
+        /*
+         * If we use PSL_TYPE_ANY, any TLD (top-level domain, i.e., domain
+         * with no dots) is considered *public* by the PSL library even if
+         * it is *not* on the official suffix list. This is the implicit
+         * behavior of the older API function psl_is_public_suffix().
+         * To inhibit that and only deem TLDs explicitly listed in the PSL
+         * as public, we need to turn off the "prevailing star rule" with
+         * PSL_TYPE_NO_STAR_RULE.
+         * For documentation on psl_is_public_suffix2(), see:
+         * https://rockdaboot.github.io/libpsl/libpsl-Public-Suffix-List-functions.html#psl-is-public-suffix2
+         * For more on the public suffix format, including wildcards:
+         * https://github.com/publicsuffix/list/wiki/Format#format
+         */
+        is_pub =
+            psl_is_public_suffix2(psl_builtin(),
+                                  domain,
+                                  assume_any_tld_is_public ? PSL_TYPE_ANY : PSL_TYPE_NO_STAR_RULE);
+#else
+        is_pub = psl_is_public_suffix(psl_builtin(), domain);
 #endif
+
+        if (is_pub)
+            return FALSE;
+    }
+
     return TRUE;
 }
 
@@ -533,7 +568,7 @@ add_dns_domains(GPtrArray            *array,
         str = searches[i];
         if (!include_routing && domain_is_routing(str))
             continue;
-        if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
+        if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE, TRUE))
             continue;
         add_string_item(array, str, dup);
     }
@@ -542,7 +577,7 @@ add_dns_domains(GPtrArray            *array,
             str = domains[i];
             if (!include_routing && domain_is_routing(str))
                 continue;
-            if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
+            if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE, TRUE))
                 continue;
             add_string_item(array, str, dup);
         }
@@ -647,7 +682,7 @@ run_netconfig(NMDnsManager *self, GError **error, int *stdin_fd)
     if (!g_spawn_async_with_pipes(NULL,
                                   argv,
                                   NULL,
-                                  G_SPAWN_DO_NOT_REAP_CHILD,
+                                  G_SPAWN_CLOEXEC_PIPES | G_SPAWN_DO_NOT_REAP_CHILD,
                                   NULL,
                                   NULL,
                                   &pid,
@@ -1236,7 +1271,7 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf)
         for (i = 0; searches[i]; i++) {
             if (domain_is_routing(searches[i]))
                 continue;
-            if (!domain_is_valid(searches[i], FALSE))
+            if (!domain_is_valid(searches[i], FALSE, TRUE))
                 continue;
             add_string_item(rc->searches, searches[i], TRUE);
         }
@@ -1946,6 +1981,7 @@ nm_dns_manager_set_ip_config(NMDnsManager         *self,
     NMDnsConfigIPData   *ip_data = NULL;
     int                  dns_priority;
     gboolean             any_removed = FALSE;
+    NMDnsConfigIPData  **p_best;
 
     g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE);
     g_return_val_if_fail(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd), FALSE);
@@ -2013,6 +2049,12 @@ nm_dns_manager_set_ip_config(NMDnsManager         *self,
             }
 
             any_removed = TRUE;
+
+            if (priv->best_ip_config_4 == ip_data_iter)
+                priv->best_ip_config_4 = NULL;
+            if (priv->best_ip_config_6 == ip_data_iter)
+                priv->best_ip_config_6 = NULL;
+
             _dns_config_ip_data_free(ip_data_iter);
         }
     }
@@ -2063,6 +2105,19 @@ nm_dns_manager_set_ip_config(NMDnsManager         *self,
         changed                 = TRUE;
     }
 
+    p_best = NM_IS_IPv4(addr_family) ? &priv->best_ip_config_4 : &priv->best_ip_config_6;
+    if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) {
+        /* Only one best-device per IP version is allowed */
+        if (*p_best != ip_data) {
+            if (*p_best)
+                (*p_best)->ip_config_type = NM_DNS_IP_CONFIG_TYPE_DEFAULT;
+            *p_best = ip_data;
+        }
+    } else {
+        if (*p_best == ip_data)
+            *p_best = NULL;
+    }
+
     if (changed)
         priv->ip_data_lst_need_sort = TRUE;
 
@@ -2100,7 +2155,8 @@ nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean s
 
     /* Certain hostnames we don't want to include in resolv.conf 'searches' */
     if (hostname && nm_utils_is_specific_hostname(hostname)
-        && !g_str_has_suffix(hostname, ".in-addr.arpa") && !nm_inet_is_valid(AF_UNSPEC, hostname)) {
+        && !NM_STR_HAS_SUFFIX(hostname, ".in-addr.arpa")
+        && !nm_inet_is_valid(AF_UNSPEC, hostname)) {
         domain = strchr(hostname, '.');
         if (domain) {
             domain++;
@@ -2111,11 +2167,16 @@ nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean s
              * specified, this makes a good default.) However, if the
              * hostname is the top level of a domain (eg, "example.com"),
              * then use the hostname itself as the search (since the user
-             * is unlikely to want "com" as a search domain).a
+             * is unlikely to want "com" as a search domain).
+             *
+             * Because that logic only applies to public domains, the
+             * "assume_any_tld_is_public" parameter is FALSE. For
+             * example, it is likely that the user *does* want "local"
+             * or "localdomain" as a search domain.
              */
-            if (domain_is_valid(domain, TRUE)) {
+            if (domain_is_valid(domain, TRUE, FALSE)) {
                 /* pass */
-            } else if (domain_is_valid(hostname, TRUE)) {
+            } else if (domain_is_valid(hostname, TRUE, FALSE)) {
                 domain = hostname;
             }
 
@@ -2127,6 +2188,8 @@ nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean s
     if (!nm_strdup_reset(&priv->hostdomain, domain))
         return;
 
+    _LOGT("set host domain to %s%s%s", NM_PRINT_FMT_QUOTE_STRING(priv->hostdomain));
+
     if (skip_update)
         return;
 
@@ -2779,6 +2842,9 @@ dispose(GObject *object)
 
     nm_clear_g_source_inst(&priv->update_pending_unblock);
 
+    priv->best_ip_config_4 = NULL;
+    priv->best_ip_config_6 = NULL;
+
     c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_data_lst_head, ip_data_lst)
         _dns_config_ip_data_free(ip_data);