From 546b75a9b15c85e4d38ed54ea5fb112a39135684 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 8 Jan 2018 12:54:48 +0100 Subject: [PATCH 1/2] libidn2 support. Thanks Paul Wouters --- ChangeLog | 3 ++ README.md | 8 ++-- configure.ac | 65 +++++++++++++++++++++++++++++--- src/convert.c | 101 +++++++++++++++++++++++++------------------------- 4 files changed, 117 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 575855cd..6b372592 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +* 2018-0?-??: Version 1.?.? + * libidn2 support. Thanks Paul Wouters + * 2017-12-21: Version 1.3.0 * Bugfix #300: Detect dnsmasq and skip unit test that fails with it. Thanks Tim Rühsen and Konomi Kitten diff --git a/README.md b/README.md index aacfc289..eb662b18 100644 --- a/README.md +++ b/README.md @@ -70,13 +70,13 @@ If you are installing from packages, you have to install the library and also th External dependencies are linked outside the getdns API build tree (we rely on configure to find them). We would like to keep the dependency tree short. Please refer to section for building on Windows for separate dependency and build instructions for that platform. * [libunbound from NLnet Labs](https://unbound.net/) version 1.4.16 or later. -* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1. (Note that the libidn version means the conversions between A-labels and U-labels may permit conversion of formally invalid labels under IDNA2008.) +* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1 or 2. (Note that the libidn version means the conversions between A-labels and U-labels may permit conversion of formally invalid labels under IDNA2008.) * [libssl and libcrypto from the OpenSSL Project](https://www.openssl.org/) version 0.9.7 or later. (Note: version 1.0.1 or later is required for TLS support, version 1.0.2 or later is required for TLS hostname authentication) * Doxygen is used to generate documentation; while this is not technically necessary for the build it makes things a lot more pleasant. For example, to build on a recent version of Ubuntu, you would need the following packages: - # apt install build-essential libunbound-dev libidn11-dev libssl-dev libtool m4 autoconf + # apt install build-essential libunbound-dev libidn2-dev libssl-dev libtool m4 autoconf If you are building from git, you need to do the following before building: @@ -98,8 +98,8 @@ Note: If you only want to build stubby, then use the `--with-stubby` option when ## Minimizing dependencies * getdns can be configured for stub resolution mode only with the `--enable-stub-only` option to configure. This removes the dependency on `libunbound`. -* Currently getdns only offers two helper functions to deal with IDN: `getdns_convert_ulabel_to_alabel` and `getdns_convert_alabel_to_ulabel`. If you do not need these functions, getdns can be configured to compile without them with the `--without-libidn` option to configure. -* When both `--enable-stub-only` and `--without-libidn` options are used, getdns has only one dependency left, which is OpenSSL. +* Currently getdns only offers two helper functions to deal with IDN: `getdns_convert_ulabel_to_alabel` and `getdns_convert_alabel_to_ulabel`. If you do not need these functions, getdns can be configured to compile without them with the `--without-libidn` and `--without-libidn2` options to configure. +* When `--enable-stub-only`, `--without-libidn` and `--without-libidn2` options are used, getdns has only one dependency left, which is OpenSSL. ## Extensions and Event loop dependencies diff --git a/configure.ac b/configure.ac index 9bc7f66a..caf2cdf3 100644 --- a/configure.ac +++ b/configure.ac @@ -763,6 +763,39 @@ else fi fi +my_with_libidn2=1 +AC_ARG_WITH(libidn2, AS_HELP_STRING([--with-libidn2=pathname], + [path to libidn2 (default: search /usr/local ..)]), + [], [withval="yes"]) +if test x_$withval = x_yes; then + for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do + if test -f "$dir/include/idn2.h"; then + CFLAGS="$CFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + AC_MSG_NOTICE([Found libidn2 in $dir]) + break + fi + if test -f "$dir/include/idn2/idn2.h"; then + CFLAGS="$CFLAGS -I$dir/include/idn2" + LDFLAGS="$LDFLAGS -L$dir/lib" + AC_MSG_NOTICE([Found libidn2 in $dir]) + break + fi + done + if test -f "/usr/include/idn2/idn2.h"; then + CFLAGS="$CFLAGS -I/usr/include/idn2" + #LDFLAGS="$LDFLAGS -L/usr/lib" + AC_MSG_NOTICE([Found libidn2 in /usr]) + fi +else + if test x_$withval != x_no; then + CFLAGS="$CFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" + else + my_with_libidn2=0 + fi +fi + if test $my_with_libunbound = 1 then # find libunbound @@ -793,15 +826,37 @@ fi found_all_libs=1 MISSING_DEPS="" MISSING_SEP="" -if test $my_with_libidn = 1 + +working_libidn2=0 +if test $my_with_libidn2 = 1 then - AC_MSG_NOTICE([Checking for dependency libidn]) - AC_CHECK_LIB([idn], [idna_to_ascii_8z], [], [ - MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libidn" + AC_MSG_NOTICE([Checking for dependency libidn2]) + AC_CHECK_LIB([idn2], [idn2_to_unicode_8z8z], [ + working_libidn2=1 + LIBS="-lidn2 $LIBS" + AC_DEFINE_UNQUOTED([HAVE_LIBIDN2], [1], [Define to 1 if you have the `idn2' library (-lidn).]) dnl ` + ], [ + MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libidn2" MISSING_SEP=", " - found_all_libs=0 ]) fi +if test $working_libidn2 = 0 +then + if test $my_with_libidn = 1 + then + AC_MSG_NOTICE([Checking for dependency libidn]) + AC_CHECK_LIB([idn], [idna_to_ascii_8z], [], [ + MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libidn" + MISSING_SEP=", " + found_all_libs=0 + ]) + else + if test $my_with_libidn2 = 1 + then + found_all_libs=0 + fi + fi +fi AC_ARG_ENABLE(unbound-event-api, AC_HELP_STRING([--disable-unbound-event-api], [Disable usage of libunbounds event API])) case "$enable_unbound_event_api" in diff --git a/src/convert.c b/src/convert.c index 71f25491..695cbf27 100644 --- a/src/convert.c +++ b/src/convert.c @@ -39,7 +39,9 @@ #ifndef USE_WINSOCK #include #endif -#ifdef HAVE_LIBIDN +#if defined(HAVE_LIBIDN2) +#include +#elif defined(HAVE_LIBIDN) #include #include #endif @@ -113,48 +115,44 @@ getdns_convert_fqdn_to_dns_name( char * getdns_convert_ulabel_to_alabel(const char *ulabel) { -#ifdef HAVE_LIBIDN - int ret; - char *buf; - char *prepped; - char *prepped2; +#if defined(HAVE_LIBIDN2) + char *alabel; - if (ulabel == NULL) - return 0; - prepped2 = malloc(BUFSIZ); - if(!prepped2) - return 0; - setlocale(LC_ALL, ""); - if ((prepped = stringprep_locale_to_utf8(ulabel)) == 0) { - /* convert to utf8 fails, which it can, but continue anyway */ - if(strlen(ulabel)+1 > BUFSIZ) { - free(prepped2); - return 0; - } - memcpy(prepped2, ulabel, strlen(ulabel)+1); - } else { - if(strlen(prepped)+1 > BUFSIZ) { - free(prepped); - free(prepped2); - return 0; - } - memcpy(prepped2, prepped, strlen(prepped)+1); - free(prepped); - } - if ((ret = stringprep(prepped2, BUFSIZ, 0, stringprep_nameprep)) != STRINGPREP_OK) { - free(prepped2); - return 0; - } - if ((ret = idna_to_ascii_8z(prepped2, &buf, 0)) != IDNA_SUCCESS) { - free(prepped2); - return 0; - } - free(prepped2); - return buf; + if (!ulabel) return NULL; + + if (idn2_lookup_ul(ulabel, &alabel, IDN2_NONTRANSITIONAL) == IDN2_OK + || idn2_lookup_ul(ulabel, &alabel, IDN2_TRANSITIONAL) == IDN2_OK) + return alabel; + +#elif defined(HAVE_LIBIDN) + char *alabel; + char *prepped; + char prepped2[BUFSIZ]; + + if (!ulabel) return NULL; + + setlocale(LC_ALL, ""); + if ((prepped = stringprep_locale_to_utf8(ulabel))) { + if(strlen(prepped)+1 > BUFSIZ) { + free(prepped); + return NULL; + } + memcpy(prepped2, prepped, strlen(prepped)+1); + free(prepped); + + /* convert to utf8 fails, which it can, but continue anyway */ + } else if (strlen(ulabel)+1 > BUFSIZ) + return NULL; + else + memcpy(prepped2, ulabel, strlen(ulabel)+1); + + if (stringprep(prepped2, BUFSIZ, 0, stringprep_nameprep) == STRINGPREP_OK + && idna_to_ascii_8z(prepped2, &alabel, 0) == IDNA_SUCCESS) + return alabel; #else - (void)ulabel; - return NULL; + (void)ulabel; #endif + return NULL; } /*---------------------------------------- getdns_convert_alabel_to_ulabel */ @@ -171,20 +169,21 @@ getdns_convert_ulabel_to_alabel(const char *ulabel) char * getdns_convert_alabel_to_ulabel(const char *alabel) { -#ifdef HAVE_LIBIDN - int ret; /* just in case we might want to use it someday */ - char *buf; +#if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN) + char *ulabel; - if (alabel == NULL) - return 0; - if ((ret = idna_to_unicode_8z8z(alabel, &buf, 0)) != IDNA_SUCCESS) { - return NULL; - } - return buf; + if (!alabel) return NULL; + +# if defined(HAVE_LIBIDN2) + if (idn2_to_unicode_8z8z(alabel, &ulabel, 0) != IDN2_OK) +# else + if (idna_to_unicode_8z8z(alabel, &ulabel, 0) != IDNA_SUCCESS) +# endif + return ulabel; #else - (void)alabel; - return NULL; + (void)alabel; #endif + return NULL; } From 9e34588f197e4b634adfcd7f89f583a27008db98 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 8 Jan 2018 16:04:40 +0100 Subject: [PATCH 2/2] logic error --- src/convert.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/convert.c b/src/convert.c index 695cbf27..03a27af2 100644 --- a/src/convert.c +++ b/src/convert.c @@ -175,9 +175,9 @@ getdns_convert_alabel_to_ulabel(const char *alabel) if (!alabel) return NULL; # if defined(HAVE_LIBIDN2) - if (idn2_to_unicode_8z8z(alabel, &ulabel, 0) != IDN2_OK) + if (idn2_to_unicode_8z8z(alabel, &ulabel, 0) == IDN2_OK) # else - if (idna_to_unicode_8z8z(alabel, &ulabel, 0) != IDNA_SUCCESS) + if (idna_to_unicode_8z8z(alabel, &ulabel, 0) == IDNA_SUCCESS) # endif return ulabel; #else