mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-20 07:00:05 +01:00
merge: branch 'bg/dns-server-valid'
libnm: add nm_dns_server_validate() https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2251
This commit is contained in:
commit
11da867072
13 changed files with 152 additions and 44 deletions
|
|
@ -374,7 +374,7 @@ server_builder_append_base(GVariantBuilder *argument_builder,
|
|||
NMDnsServer dns_server;
|
||||
gsize addr_size;
|
||||
|
||||
if (!nm_dns_uri_parse(address_family, address_string, &dns_server))
|
||||
if (!nm_dns_uri_parse(address_family, address_string, &dns_server, NULL))
|
||||
return FALSE;
|
||||
addr_size = nm_utils_addr_family_to_size(dns_server.addr_family);
|
||||
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ update_add_ip_config(NMDnsSystemdResolved *self,
|
|||
for (i = 0; i < n; i++) {
|
||||
NMDnsServer dns_server;
|
||||
|
||||
if (!nm_dns_uri_parse(ip_data->addr_family, strarr[i], &dns_server))
|
||||
if (!nm_dns_uri_parse(ip_data->addr_family, strarr[i], &dns_server, NULL))
|
||||
continue;
|
||||
|
||||
if (!NM_IN_SET(dns_server.scheme,
|
||||
|
|
|
|||
|
|
@ -3987,7 +3987,7 @@ _l3cfg_routed_dns_apply(NML3Cfg *self, const NML3ConfigData *l3cd)
|
|||
NMDnsServer dns;
|
||||
int r;
|
||||
|
||||
if (!nm_dns_uri_parse(addr_family, nameservers[i], &dns))
|
||||
if (!nm_dns_uri_parse(addr_family, nameservers[i], &dns, NULL))
|
||||
continue;
|
||||
|
||||
/* Find the gateway to the DNS over the current interface. When
|
||||
|
|
|
|||
|
|
@ -2058,6 +2058,7 @@ make_ip4_setting(shvarFile *ifcfg,
|
|||
for (i = 1; i < 10000; i++) {
|
||||
NMDnsServer dns;
|
||||
char tag[256];
|
||||
gs_free_error GError *local = NULL;
|
||||
|
||||
numbered_tag(tag, "DNS", i);
|
||||
nm_clear_g_free(&value);
|
||||
|
|
@ -2065,12 +2066,13 @@ make_ip4_setting(shvarFile *ifcfg,
|
|||
if (!v)
|
||||
break;
|
||||
|
||||
if (!nm_dns_uri_parse(AF_UNSPEC, v, &dns)) {
|
||||
if (!nm_dns_uri_parse(AF_UNSPEC, v, &dns, &local)) {
|
||||
g_set_error(error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid DNS server address '%s'",
|
||||
v);
|
||||
"Invalid DNS server address '%s': %s",
|
||||
v,
|
||||
local->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -2607,6 +2609,7 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea
|
|||
* Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting())
|
||||
*/
|
||||
for (i = 1; i < 10000; i++) {
|
||||
gs_free_error GError *err = NULL;
|
||||
NMDnsServer dns;
|
||||
char tag[256];
|
||||
|
||||
|
|
@ -2616,14 +2619,15 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea
|
|||
if (!v)
|
||||
break;
|
||||
|
||||
if (!nm_dns_uri_parse(AF_UNSPEC, v, &dns)) {
|
||||
if (!nm_dns_uri_parse(AF_UNSPEC, v, &dns, &err)) {
|
||||
if (is_disabled)
|
||||
continue;
|
||||
g_set_error(error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
"Invalid DNS server address '%s'",
|
||||
v);
|
||||
"Invalid DNS server address '%s': %s",
|
||||
v,
|
||||
err->message);
|
||||
return NULL;
|
||||
}
|
||||
if (dns.addr_family == AF_INET6) {
|
||||
|
|
|
|||
|
|
@ -2076,3 +2076,8 @@ global:
|
|||
nm_setting_sriov_get_preserve_on_down;
|
||||
nm_sriov_preserve_on_down_get_type;
|
||||
} libnm_1_52_0;
|
||||
|
||||
libnm_1_56_0 {
|
||||
global:
|
||||
nm_dns_server_validate;
|
||||
} libnm_1_54_0;
|
||||
|
|
|
|||
|
|
@ -705,6 +705,7 @@ nm_mptcp_flags_normalize(NMMptcpFlags flags)
|
|||
* @addr_family: the address family, or AF_UNSPEC to autodetect it
|
||||
* @str: the name server URI string to parse
|
||||
* @dns: the name server descriptor to fill, or %NULL
|
||||
* @error: the error to set if the string cannot be parsed
|
||||
*
|
||||
* Parses the given name server URI string. Each name server is represented
|
||||
* by the following grammar:
|
||||
|
|
@ -731,7 +732,7 @@ nm_mptcp_flags_normalize(NMMptcpFlags flags)
|
|||
* Returns: %TRUE on success, %FALSE on failure
|
||||
*/
|
||||
gboolean
|
||||
nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns)
|
||||
nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns, GError **error)
|
||||
{
|
||||
NMDnsServer dns_stack;
|
||||
gs_free char *addr_port_heap = NULL;
|
||||
|
|
@ -746,8 +747,13 @@ nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns)
|
|||
if (!dns)
|
||||
dns = &dns_stack;
|
||||
|
||||
if (!str)
|
||||
if (!str) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("the string is empty"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*dns = (NMDnsServer) {0};
|
||||
|
||||
|
|
@ -765,12 +771,21 @@ nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns)
|
|||
}
|
||||
|
||||
if (name && name[0] == '\0') {
|
||||
/* empty DoT server name is not allowed */
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("the DNS-over-TLS server name is empty"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_inet_parse_bin(addr_family, str, &dns->addr_family, &dns->addr))
|
||||
if (!nm_inet_parse_bin(addr_family, str, &dns->addr_family, &dns->addr)) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("\"%s\" is not a valid IP address or a supported URI"),
|
||||
str);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dns->servername = name;
|
||||
dns->scheme = NM_DNS_URI_SCHEME_NONE;
|
||||
|
|
@ -784,7 +799,10 @@ nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns)
|
|||
addr_port = nm_strndup_a(100, addr_port, name - addr_port, &addr_port_heap);
|
||||
name++;
|
||||
if (*name == '\0') {
|
||||
/* empty DoT server name not allowed */
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("the DNS-over-TLS server name is empty"));
|
||||
return FALSE;
|
||||
}
|
||||
dns->servername = name;
|
||||
|
|
@ -797,8 +815,13 @@ nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns)
|
|||
addr_family = AF_INET6;
|
||||
addr_port++;
|
||||
end = strchr(addr_port, ']');
|
||||
if (!end)
|
||||
if (!end) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("unterminated square bracket"));
|
||||
return FALSE;
|
||||
}
|
||||
addr = nm_strndup_a(100, addr_port, end - addr_port, &addr_heap);
|
||||
|
||||
/* IPv6 link-local scope-id */
|
||||
|
|
@ -806,18 +829,29 @@ nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns)
|
|||
if (perc) {
|
||||
*perc = '\0';
|
||||
if (g_strlcpy(dns->interface, perc + 1, sizeof(dns->interface))
|
||||
>= sizeof(dns->interface))
|
||||
>= sizeof(dns->interface)) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("the interface name is too long"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* port */
|
||||
end++;
|
||||
if (*end == ':') {
|
||||
end++;
|
||||
dns->port = _nm_utils_ascii_str_to_int64(end, 10, 1, 65535, 0);
|
||||
if (dns->port == 0)
|
||||
if (dns->port == 0) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("\"%s\" is not a valid port number"),
|
||||
end);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else if (addr_family != AF_INET6) {
|
||||
/* square brackets are mandatory for IPv6, so it must be IPv4 */
|
||||
|
||||
|
|
@ -830,23 +864,49 @@ nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *dns)
|
|||
addr = nm_strndup_a(100, addr_port, port - addr_port, &addr_heap);
|
||||
port++;
|
||||
dns->port = _nm_utils_ascii_str_to_int64(port, 10, 1, 65535, 0);
|
||||
if (dns->port == 0)
|
||||
if (dns->port == 0) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("\"%s\" is not a valid port number"),
|
||||
port);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("IPv6 addresses must be enclosed in square brackets"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_inet_parse_bin(addr_family, addr, &dns->addr_family, &dns->addr))
|
||||
if (!nm_inet_parse_bin(addr_family, addr, &dns->addr_family, &dns->addr)) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("\"%s\" is not a valid IP address"),
|
||||
addr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dns->scheme != NM_DNS_URI_SCHEME_TLS && dns->servername)
|
||||
if (dns->scheme != NM_DNS_URI_SCHEME_TLS && dns->servername) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("the server name is only supported for DNS-over-TLS"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* For now, allow the interface only for IPv6 link-local addresses */
|
||||
if (dns->interface[0]
|
||||
&& (dns->addr_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&dns->addr.addr6)))
|
||||
&& (dns->addr_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&dns->addr.addr6))) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("the scope-id is only supported for IPv6 link-local addresses"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -870,7 +930,7 @@ nm_dns_uri_parse_plain(int addr_family, const char *str, char *out_addrstr, NMIP
|
|||
{
|
||||
NMDnsServer dns;
|
||||
|
||||
if (!nm_dns_uri_parse(addr_family, str, &dns))
|
||||
if (!nm_dns_uri_parse(addr_family, str, &dns, NULL))
|
||||
return FALSE;
|
||||
|
||||
switch (dns.scheme) {
|
||||
|
|
@ -922,7 +982,7 @@ nm_dns_uri_normalize(int addr_family, const char *str, char **out_free)
|
|||
nm_assert(str);
|
||||
nm_assert(out_free && !*out_free);
|
||||
|
||||
if (!nm_dns_uri_parse(addr_family, str, &dns))
|
||||
if (!nm_dns_uri_parse(addr_family, str, &dns, NULL))
|
||||
return NULL;
|
||||
|
||||
nm_inet_ntop(dns.addr_family, &dns.addr, addrstr);
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ typedef struct {
|
|||
guint16 port;
|
||||
} NMDnsServer;
|
||||
|
||||
gboolean nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *out_dns);
|
||||
gboolean nm_dns_uri_parse(int addr_family, const char *str, NMDnsServer *out_dns, GError **error);
|
||||
gboolean
|
||||
nm_dns_uri_parse_plain(int addr_family, const char *str, char *out_addrstr, NMIPAddr *out_addr);
|
||||
const char *nm_dns_uri_normalize(int addr_family, const char *str, char **out_free);
|
||||
|
|
|
|||
|
|
@ -1158,14 +1158,17 @@ ip_dns_parser(KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
|||
addr_family = NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting);
|
||||
|
||||
for (i = 0, n = 0; i < length; i++) {
|
||||
if (!nm_dns_uri_parse(addr_family, list[i], NULL)) {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (!nm_dns_uri_parse(addr_family, list[i], NULL, &error)) {
|
||||
if (!read_handle_warn(info,
|
||||
key,
|
||||
key,
|
||||
NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("ignoring invalid DNS server IPv%c address '%s'"),
|
||||
_("ignoring invalid DNS server IPv%c address '%s': %s"),
|
||||
nm_utils_addr_family_to_char(addr_family),
|
||||
list[i])) {
|
||||
list[i],
|
||||
error->message)) {
|
||||
do {
|
||||
nm_clear_g_free(&list[i]);
|
||||
} while (++i < length);
|
||||
|
|
|
|||
|
|
@ -4221,6 +4221,25 @@ nm_setting_ip_config_clear_dns(NMSettingIPConfig *setting)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_dns_server_validate:
|
||||
* @str: the string containing the DNS server
|
||||
* @family: the IP address family (%AF_INET for IPv4, %AF_INET6 for IPv6,
|
||||
* %AF_UNSPEC to accept both IPv4 and IPv6)
|
||||
* @error: (nullable): a pointer to %NULL #GError, or %NULL
|
||||
*
|
||||
* Validates a DNS name server string.
|
||||
*
|
||||
* Return: %TRUE if the name server is valid, %FALSE otherwise
|
||||
*
|
||||
* Since: 1.56
|
||||
*/
|
||||
gboolean
|
||||
nm_dns_server_validate(const char *str, int family, GError **error)
|
||||
{
|
||||
return nm_dns_uri_parse(family, str, NULL, error);
|
||||
}
|
||||
|
||||
GPtrArray *
|
||||
_nm_setting_ip_config_get_dns_array(NMSettingIPConfig *setting)
|
||||
{
|
||||
|
|
@ -5631,13 +5650,18 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
|||
if (priv->dns) {
|
||||
for (i = 0; i < priv->dns->len; i++) {
|
||||
const char *dns = priv->dns->pdata[i];
|
||||
gs_free_error GError *local = NULL;
|
||||
|
||||
if (!nm_dns_uri_parse(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting), dns, NULL)) {
|
||||
if (!nm_dns_uri_parse(NM_SETTING_IP_CONFIG_GET_ADDR_FAMILY(setting),
|
||||
dns,
|
||||
NULL,
|
||||
&local)) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("%u. DNS server address is invalid"),
|
||||
(i + 1u));
|
||||
_("%u. DNS server address is invalid: %s"),
|
||||
(i + 1u),
|
||||
local->message);
|
||||
g_prefix_error(error,
|
||||
"%s.%s: ",
|
||||
nm_setting_get_name(setting),
|
||||
|
|
|
|||
|
|
@ -11400,12 +11400,16 @@ test_connection_path(void)
|
|||
static void
|
||||
t_dns_0(const char *str)
|
||||
{
|
||||
gs_free_error GError *error = NULL;
|
||||
NMDnsServer server = {};
|
||||
gboolean ret;
|
||||
|
||||
ret = nm_dns_uri_parse(AF_UNSPEC, str, &server);
|
||||
ret = nm_dns_uri_parse(AF_UNSPEC, str, &server, &error);
|
||||
|
||||
g_assert(!ret);
|
||||
g_assert(error);
|
||||
g_assert(error->message);
|
||||
g_assert(error->message[0] != '\0');
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -11422,10 +11426,12 @@ dns_uri_parse_ok(const char *str,
|
|||
gboolean ret;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
gs_free_error GError *error = NULL;
|
||||
gboolean af_unspec = i;
|
||||
|
||||
ret = nm_dns_uri_parse(af_unspec ? AF_UNSPEC : addr_family, str, &dns);
|
||||
ret = nm_dns_uri_parse(af_unspec ? AF_UNSPEC : addr_family, str, &dns, &error);
|
||||
g_assert(ret);
|
||||
g_assert_no_error(error);
|
||||
|
||||
g_assert_cmpint(addr_family, ==, dns.addr_family);
|
||||
g_assert_cmpint(port, ==, dns.port);
|
||||
|
|
@ -11436,8 +11442,9 @@ dns_uri_parse_ok(const char *str,
|
|||
g_assert_cmpstr(addrstr, ==, addr);
|
||||
|
||||
/* Parse with the wrong address family must fail */
|
||||
ret = nm_dns_uri_parse(addr_family == AF_INET ? AF_INET6 : AF_INET, str, &dns);
|
||||
ret = nm_dns_uri_parse(addr_family == AF_INET ? AF_INET6 : AF_INET, str, &dns, &error);
|
||||
g_assert(!ret);
|
||||
g_assert(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -567,6 +567,9 @@ int nm_setting_ip_config_get_shared_dhcp_lease_time(NMSettingIPConfig *setting);
|
|||
NM_AVAILABLE_IN_1_54
|
||||
NMSettingIPConfigForwarding nm_setting_ip_config_get_forwarding(NMSettingIPConfig *setting);
|
||||
|
||||
NM_AVAILABLE_IN_1_56
|
||||
gboolean nm_dns_server_validate(const char *str, int family, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* NM_SETTING_IP_CONFIG_H */
|
||||
|
|
|
|||
|
|
@ -1273,8 +1273,10 @@ reader_parse_rd_znet(Reader *reader, char *argument, gboolean net_ifnames)
|
|||
static void
|
||||
reader_parse_global_dns(Reader *reader, char *argument)
|
||||
{
|
||||
if (!nm_dns_uri_parse(AF_UNSPEC, argument, NULL)) {
|
||||
_LOGW(LOGD_CORE, "rd.net.dns: invalid server '%s'", argument);
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (!nm_dns_uri_parse(AF_UNSPEC, argument, NULL, &error)) {
|
||||
_LOGW(LOGD_CORE, "rd.net.dns: invalid server '%s': %s", argument, error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2664,7 +2664,7 @@ test_global_dns(void)
|
|||
gs_free char *dns_resolve_mode = NULL;
|
||||
gint64 carrier_timeout_sec = 0;
|
||||
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.net.dns: invalid server 'foobar'");
|
||||
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.net.dns: invalid server 'foobar':*");
|
||||
connections = _parse(ARGV,
|
||||
&hostname,
|
||||
&carrier_timeout_sec,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue