resolved: support libidn2 in addition to libidn
libidn2 2.0.0 supports IDNA2008, in contrast to libidn which supports IDNA2003. https://bugzilla.redhat.com/show_bug.cgi?id=1449145 From that bug report: Internationalized domain names exist for quite some time (IDNA2003), although the protocols describing them have evolved in an incompatible way (IDNA2008). These incompatibilities will prevent applications written for IDNA2003 to access certain problematic domain names defined with IDNA2008, e.g., faß.de is translated to domain xn--fa-hia.de with IDNA2008, while in IDNA2003 it is translated to fass.de domain. That not only causes incompatibility problems, but may be used as an attack vector to redirect users to different web sites. v2: - keep libidn support - require libidn2 >= 2.0.0 v3: - keep dns_name_apply_idna caller dumb, and keep the #ifdefs inside of the function. - use both ±IDN and ±IDN2 in the version string
This commit is contained in:
@@ -309,8 +309,8 @@ int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bo
|
||||
r = dns_name_apply_idna(name, &buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
name = buf;
|
||||
if (r > 0)
|
||||
name = buf;
|
||||
}
|
||||
|
||||
q = dns_question_new(family == AF_UNSPEC ? 2 : 1);
|
||||
@@ -422,8 +422,8 @@ int dns_question_new_service(
|
||||
r = dns_name_apply_idna(domain, &buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
domain = buf;
|
||||
if (r > 0)
|
||||
domain = buf;
|
||||
}
|
||||
|
||||
r = dns_service_join(service, type, domain, &joined);
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include <poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef HAVE_LIBIDN2
|
||||
#include <idn2.h>
|
||||
#endif
|
||||
|
||||
#include "af-list.h"
|
||||
#include "alloc-util.h"
|
||||
#include "dirent-util.h"
|
||||
@@ -324,9 +328,14 @@ static int manager_network_monitor_listen(Manager *m) {
|
||||
|
||||
static int determine_hostname(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) {
|
||||
_cleanup_free_ char *h = NULL, *n = NULL;
|
||||
#if defined(HAVE_LIBIDN2)
|
||||
_cleanup_free_ char *utf8 = NULL;
|
||||
#elif defined(HAVE_LIBIDN)
|
||||
int k;
|
||||
#endif
|
||||
char label[DNS_LABEL_MAX];
|
||||
const char *p;
|
||||
int r, k;
|
||||
const char *p, *decoded;
|
||||
int r;
|
||||
|
||||
assert(full_hostname);
|
||||
assert(llmnr_hostname);
|
||||
@@ -339,7 +348,7 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
|
||||
return log_debug_errno(r, "Can't determine system hostname: %m");
|
||||
|
||||
p = h;
|
||||
r = dns_label_unescape(&p, label, sizeof(label));
|
||||
r = dns_label_unescape(&p, label, sizeof label);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to unescape host name: %m");
|
||||
if (r == 0) {
|
||||
@@ -347,7 +356,16 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
k = dns_label_undo_idna(label, r, label, sizeof(label));
|
||||
#if defined(HAVE_LIBIDN2)
|
||||
r = idn2_to_unicode_8z8z(label, &utf8, 0);
|
||||
if (r != IDN2_OK)
|
||||
return log_error("Failed to undo IDNA: %s", idn2_strerror(r));
|
||||
assert(utf8_is_valid(utf8));
|
||||
|
||||
r = strlen(utf8);
|
||||
decoded = utf8;
|
||||
#elif defined(HAVE_LIBIDN)
|
||||
k = dns_label_undo_idna(label, r, label, sizeof label);
|
||||
if (k < 0)
|
||||
return log_error_errno(k, "Failed to undo IDNA: %m");
|
||||
if (k > 0)
|
||||
@@ -357,8 +375,12 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char
|
||||
log_error("System hostname is not UTF-8 clean.");
|
||||
return -EINVAL;
|
||||
}
|
||||
decoded = label;
|
||||
#else
|
||||
decoded = label; /* no decoding */
|
||||
#endif
|
||||
|
||||
r = dns_label_escape_new(label, r, &n);
|
||||
r = dns_label_escape_new(decoded, r, &n);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to escape host name: %m");
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ int main(int argc, char* argv[]) {
|
||||
test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
|
||||
test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
|
||||
|
||||
#ifdef HAVE_LIBIDN
|
||||
#if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN)
|
||||
/* Unsigned A with IDNA conversion necessary */
|
||||
test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL);
|
||||
test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL);
|
||||
|
||||
Reference in New Issue
Block a user