Merge pull request #5928 from keszybz/libidn2

Use idn2 instead of idn
This commit is contained in:
Lennart Poettering 2017-05-12 12:01:40 +02:00 committed by GitHub
commit 3823da25cf
15 changed files with 122 additions and 37 deletions

View File

@ -48,7 +48,7 @@ BuildPackages=
kmod
libcap
libgcrypt
libidn
libidn2
libmicrohttpd
libseccomp
libtool

View File

@ -53,7 +53,7 @@ BuildPackages=
libfdisk-dev
libgcrypt20-dev
libgnutls28-dev
libidn11-dev
libidn2-dev
libkmod-dev
liblzma-dev
liblz4-dev

View File

@ -53,7 +53,7 @@ BuildPackages=
libcap-devel
libcurl-devel
libgcrypt-devel
libidn-devel
libidn2-devel
libmicrohttpd-devel
libmount-devel
libseccomp-devel

View File

@ -1137,6 +1137,7 @@ libshared_la_CFLAGS = \
$(AM_CFLAGS) \
$(ACL_CFLAGS) \
$(LIBIDN_CFLAGS) \
$(LIBIDN2_CFLAGS) \
$(SECCOMP_CFLAGS) \
$(BLKID_CFLAGS) \
$(LIBCRYPTSETUP_CFLAGS)
@ -1148,6 +1149,7 @@ libshared_la_LIBADD = \
libudev-internal.la \
$(ACL_LIBS) \
$(LIBIDN_LIBS) \
$(LIBIDN2_LIBS) \
$(SECCOMP_LIBS) \
$(BLKID_LIBS) \
$(LIBCRYPTSETUP_LIBS)
@ -1171,6 +1173,7 @@ libsystemd_shared_la_CFLAGS = \
$(libudev_internal_la_CFLAGS) \
$(ACL_CFLAGS) \
$(LIBIDN_CFLAGS) \
$(LIBIDN2_CFLAGS) \
$(SECCOMP_CFLAGS) \
$(BLKID_CFLAGS) \
$(LIBCRYPTSETUP_CFLAGS) \
@ -1185,6 +1188,7 @@ libsystemd_shared_la_LIBADD = \
$(libudev_internal_la_LIBADD) \
$(ACL_LIBS) \
$(LIBIDN_LIBS) \
$(LIBIDN2_LIBS) \
$(SECCOMP_LIBS) \
$(BLKID_LIBS) \
$(LIBCRYPTSETUP_LIBS)

2
README
View File

@ -143,7 +143,7 @@ REQUIREMENTS:
libqrencode (optional)
libmicrohttpd (optional)
libpython (optional)
libidn (optional)
libidn2 or libidn (optional)
elfutils >= 158 (optional)
make, gcc, and similar tools

View File

@ -1015,16 +1015,32 @@ AM_CONDITIONAL(HAVE_LIBCURL, [test "$have_libcurl" = "yes"])
AM_CONDITIONAL(HAVE_REMOTE, [test "$have_microhttpd" = "yes" -o "$have_libcurl" = "yes"])
# ------------------------------------------------------------------------------
have_libidn2=no
AC_ARG_ENABLE(libidn2, AS_HELP_STRING([--disable-libidn2], [disable optional LIBIDN2 support]))
if test "x$enable_libidn2" != "xno"; then
PKG_CHECK_MODULES(LIBIDN2, [libidn2 >= 2.0.0],
[AC_DEFINE(HAVE_LIBIDN2, 1, [Define if libidn2 is available])
have_libidn2=yes
M4_DEFINES="$M4_DEFINES -DHAVE_LIBIDN2"],
[have_libidn2=no])
if test "x$have_libidn2" = "xno" -a "x$enable_libidn2" = "xyes"; then
AC_MSG_ERROR([*** libidn2 support requested but libraries not found])
fi
fi
AM_CONDITIONAL(HAVE_LIBIDN2, [test "$have_libidn2" = "yes"])
have_libidn=no
AC_ARG_ENABLE(libidn, AS_HELP_STRING([--disable-libidn], [disable optional LIBIDN support]))
if test "x$enable_libidn" != "xno"; then
PKG_CHECK_MODULES(LIBIDN, [libidn],
[AC_DEFINE(HAVE_LIBIDN, 1, [Define if libidn is available])
have_libidn=yes
M4_DEFINES="$M4_DEFINES -DHAVE_LIBIDN"],
[have_libidn=no])
if test "x$have_libidn" = "xno" -a "x$enable_libidn" = "xyes"; then
AC_MSG_ERROR([*** libidn support requested but libraries not found])
if test "$have_libidn2" != "yes"; then
if test "x$enable_libidn" != "xno"; then
PKG_CHECK_MODULES(LIBIDN, [libidn],
[AC_DEFINE(HAVE_LIBIDN, 1, [Define if libidn is available])
have_libidn=yes
M4_DEFINES="$M4_DEFINES -DHAVE_LIBIDN"],
[have_libidn=no])
if test "x$have_libidn" = "xno" -a "x$enable_libidn" = "xyes"; then
AC_MSG_ERROR([*** libidn support requested but libraries not found])
fi
fi
fi
AM_CONDITIONAL(HAVE_LIBIDN, [test "$have_libidn" = "yes"])
@ -1720,6 +1736,7 @@ AC_MSG_RESULT([
MICROHTTPD: ${have_microhttpd}
GNUTLS: ${have_gnutls}
libcurl: ${have_libcurl}
libidn2: ${have_libidn2}
libidn: ${have_libidn}
libiptc: ${have_libiptc}
ELFUTILS: ${have_elfutils}

View File

@ -791,15 +791,29 @@ else
endif
want_libidn = get_option('libidn')
if want_libidn != 'false'
want_libidn2 = get_option('libidn2')
if want_libidn == 'true' and want_libidn2 == 'true'
error('libidn and libidn2 cannot be requested simultaneously')
endif
if want_libidn2 != 'false' and want_libidn != 'true'
libidn = dependency('libidn2',
required : want_libidn2 == 'true')
# libidn is used for both libidn and libidn2 objects
if libidn.found()
conf.set('HAVE_LIBIDN2', true)
m4_defines += ['-DHAVE_LIBIDN2']
endif
else
libidn = []
endif
if not conf.get('HAVE_LIBIDN2', false) and want_libidn != 'false'
libidn = dependency('libidn',
required : want_libidn == 'true')
if libidn.found()
conf.set('HAVE_LIBIDN', true)
m4_defines += ['-DHAVE_LIBIDN']
endif
else
libidn = []
endif
want_libiptc = get_option('libiptc')
@ -2429,6 +2443,7 @@ foreach tuple : [
['microhttpd'],
['gnutls'],
['libcurl'],
['libidn2'],
['libidn'],
['libiptc'],
['elfutils'],

View File

@ -197,6 +197,8 @@ option('libcryptsetup', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libcryptsetup support')
option('libcurl', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libcurl support')
option('libidn2', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libidn2 support')
option('libidn', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'libidn support')
option('libiptc', type : 'combo', choices : ['auto', 'true', 'false'],

View File

@ -127,6 +127,12 @@
#define _KMOD_FEATURE_ "-KMOD"
#endif
#ifdef HAVE_LIBIDN2
#define _IDN2_FEATURE_ "+IDN2"
#else
#define _IDN2_FEATURE_ "-IDN2"
#endif
#ifdef HAVE_LIBIDN
#define _IDN_FEATURE_ "+IDN"
#else
@ -154,5 +160,6 @@
_BLKID_FEATURE_ " " \
_ELFUTILS_FEATURE_ " " \
_KMOD_FEATURE_ " " \
_IDN2_FEATURE_ " " \
_IDN_FEATURE_ " " \
_CGROUP_HIEARCHY_

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -17,9 +17,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#ifdef HAVE_LIBIDN
#include <idna.h>
#include <stringprep.h>
#if defined(HAVE_LIBIDN2)
# include <idn2.h>
#elif defined(HAVE_LIBIDN)
# include <idna.h>
# include <stringprep.h>
#endif
#include <endian.h>
@ -299,8 +301,8 @@ int dns_label_escape_new(const char *p, size_t l, char **ret) {
return r;
}
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
#ifdef HAVE_LIBIDN
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
_cleanup_free_ uint32_t *input = NULL;
size_t input_size, l;
const char *p;
@ -348,13 +350,9 @@ int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded
decoded[l] = 0;
return (int) l;
#else
return 0;
#endif
}
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
#ifdef HAVE_LIBIDN
size_t input_size, output_size;
_cleanup_free_ uint32_t *input = NULL;
_cleanup_free_ char *result = NULL;
@ -399,10 +397,8 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
decoded[w] = 0;
return w;
#else
return 0;
#endif
}
#endif
int dns_name_concat(const char *a, const char *b, char **_ret) {
_cleanup_free_ char *ret = NULL;
@ -1274,6 +1270,23 @@ int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
}
int dns_name_apply_idna(const char *name, char **ret) {
/* Return negative on error, 0 if not implemented, positive on success. */
#if defined(HAVE_LIBIDN2)
int r;
assert(name);
assert(ret);
r = idn2_lookup_u8((uint8_t*) name, (uint8_t**) ret,
IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
if (r == IDN2_OK)
return 1; /* *ret has been written */
else if (IN_SET(r, IDN2_TOO_BIG_DOMAIN, IDN2_TOO_BIG_LABEL))
return -ENOSPC;
else
return -EINVAL;
#elif defined(HAVE_LIBIDN)
_cleanup_free_ char *buf = NULL;
size_t n = 0, allocated = 0;
bool first = true;
@ -1323,6 +1336,9 @@ int dns_name_apply_idna(const char *name, char **ret) {
buf = NULL;
return (int) n;
#else
return 0;
#endif
}
int dns_name_is_valid_or_address(const char *name) {

View File

@ -51,8 +51,10 @@ static inline int dns_name_parent(const char **name) {
return dns_label_unescape(name, NULL, DNS_LABEL_MAX);
}
#if defined(HAVE_LIBIDN)
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
#endif
int dns_name_concat(const char *a, const char *b, char **ret);

View File

@ -608,7 +608,7 @@ static void test_dns_name_common_suffix(void) {
}
static void test_dns_name_apply_idna_one(const char *s, const char *result) {
#ifdef HAVE_LIBIDN
#if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN)
_cleanup_free_ char *buf = NULL;
assert_se(dns_name_apply_idna(s, &buf) >= 0);
assert_se(dns_name_equal(buf, result) > 0);