]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add support for libidn2
authorTomas Hozza <thozza@redhat.com>
Wed, 23 Sep 2015 14:47:37 +0000 (16:47 +0200)
committerOndřej Surý <ondrej@sury.org>
Sat, 17 Mar 2018 13:13:47 +0000 (13:13 +0000)
Added two new configure options:
--with-libidn2 - to enable IDN using GNU libidn2

idnkit, libidn and libidn2 support can not be used at the same time.

NOTE: libidn2 does not support punycode back to Unicode
characters, so support for this is missing.

Signed-off-by: Tomas Hozza <thozza@redhat.com>
Removed iconv, convert directly from locale to ACE

Fix libidn2 and idnkit origin appending

Make IDN options in help less different

Signed-off-by: Petr Menšík <pemensik@redhat.com>
bin/dig/Makefile.in
bin/dig/dig.c
bin/dig/dighost.c
bin/dig/host.c
configure.in

index 72e84f21dac07f86fa2246b091fc6e5a31863de4..0545902ebb776c4e8524439d52848febd6c27e41 100644 (file)
@@ -41,10 +41,10 @@ DEPLIBS =   ${DNSDEPLIBS} ${IRSDEPLIBS} ${BIND9DEPLIBS} \
                ${ISCDEPLIBS} ${ISCCFGDEPLIBS}
 
 LIBS =         ${DNSLIBS} ${IRSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
-               ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN_LIBS@ @LIBS@
+               ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN_LIBS@ @LIBIDN2_LIBS@ @LIBS@
 
 NOSYMLIBS =    ${DNSLIBS} ${IRSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
-               ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN_LIBS@ @LIBS@
+               ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN_LIBS@ @LIBIDN2_LIBS@ @LIBS@
 
 SUBDIRS =
 
index cfe05cd7b4bb2e475ed3d5c179ab54d9c4a9c167..0181db614af398bb8ed530c2c767094887da9b3a 100644 (file)
@@ -1046,7 +1046,7 @@ plus_option(const char *option, isc_boolean_t is_batchfile,
                                break;
                        case 'n':
                                FULLCHECK("idnout");
-#ifndef WITH_IDN
+#ifndef WITH_IDN_SUPPORT
                                fprintf(stderr, ";; IDN support not enabled\n");
 #else
                                lookup->idnout = state;
index 9510506a8421d277bb1d4a6d4efb22f5086e08c2..d752d156a474c6566b757324e3073f814b29200e 100644 (file)
 #include <idna.h>
 #include <stringprep.h>
 #endif
+
+#ifdef WITH_LIBIDN2
+#include <idn2.h>
+#endif
 #endif /* WITH_IDN_SUPPORT */
 
 #include <dns/byaddr.h>
@@ -184,6 +188,17 @@ static isc_result_t libidn_utf8_to_ace(const char *from,
 static isc_result_t libidn_ace_to_locale(const char *from,
                char *to,
                size_t tolen);
+
+#elif WITH_LIBIDN2
+static isc_result_t libidn2_locale_to_utf8(const char *from,
+               char *to,
+               size_t tolen);
+static isc_result_t libidn2_utf8_to_ace(const char *from,
+               char *to,
+               size_t tolen);
+static isc_result_t libidn2_ace_to_locale(const char *from,
+               char *to,
+               size_t tolen);
 #endif
 #endif /* WITH_IDN_SUPPORT */
 
@@ -2149,6 +2164,11 @@ setup_lookup(dig_lookup_t *lookup) {
        }
        result = idn_utf8_to_ace(utf8_textname,
                                 idn_textname, sizeof(idn_textname));
+       if (lookup->origin != NULL && result == ISC_R_NOSPACE) {
+               dns_message_puttempname(lookup->sendmsg,
+                                       &lookup->name);
+               return ISC_FALSE;
+       }
        check_result(result, "convert UTF-8 textname to IDN encoding");
 
 #else /* WITH_IDN_SUPPORT */
@@ -4267,7 +4287,6 @@ destroy_libs(void) {
 static void
 idn_initialize(void) {
        isc_result_t result;
-       char *idn_disable_env = NULL;
 
 #ifdef HAVE_SETLOCALE
        /* Set locale */
@@ -4291,6 +4310,8 @@ idn_locale_to_utf8(const char *from, char *to, size_t tolen) {
        return (idnkit_locale_to_utf8(from, to, tolen));
 #elif WITH_LIBIDN
        return (libidn_locale_to_utf8(from, to, tolen));
+#else /* WITH_LIBIDN2 */
+       return (libidn2_locale_to_utf8(from, to, tolen));
 #endif
 }
 
@@ -4300,6 +4321,8 @@ idn_utf8_to_ace(const char *from, char *to, size_t tolen) {
        return (idnkit_utf8_to_ace(from, to, tolen));
 #elif WITH_LIBIDN
        return (libidn_utf8_to_ace(from, to, tolen));
+#else /* WITH_LIBIDN2 */
+       return (libidn2_utf8_to_ace(from, to, tolen));
 #endif
 }
 
@@ -4309,6 +4332,8 @@ idn_ace_to_locale(const char *from, char *to, size_t tolen) {
        return (idnkit_ace_to_locale(from, to, tolen));
 #elif WITH_LIBIDN
        return (libidn_ace_to_locale(from, to, tolen));
+#else /* WITH_LIBIDN2 */
+       return (libidn2_ace_to_locale(from, to, tolen));
 #endif
 }
 
@@ -4378,7 +4403,7 @@ append_textname(char *name, const char *origin, size_t namesize) {
        /* Append dot and origin */
        if (namelen + 1 + originlen >= namesize) {
                debug("append_textname failure: name + origin is too long");
-               return (ISC_R_FAILURE);
+               return (ISC_R_NOSPACE);
        }
 
        if (*origin != '.')
@@ -4414,7 +4439,10 @@ idnkit_locale_to_utf8(const char *from, char *to, size_t tolen) {
        } else {
                debug("idnkit idn_encodename failed: %s",
                      idn_result_tostring(result));
-               return (ISC_R_FAILURE);
+               if (result == idn_invalid_length)
+                       return (ISC_R_NOSPACE);
+               else
+                       return (ISC_R_FAILURE);
        }
 }
 
@@ -4478,7 +4506,6 @@ cleanup:
 static isc_result_t
 libidn_utf8_to_ace(const char *from, char *to, size_t tolen) {
        int res;
-       isc_result_t result;
        char *tmp_str = NULL;
 
        res = idna_to_ascii_8z(from, &tmp_str, 0);
@@ -4487,22 +4514,18 @@ libidn_utf8_to_ace(const char *from, char *to, size_t tolen) {
                /* check the length */
                if (strlen(tmp_str) >= tolen) {
                        debug("encoded ASC string is too long");
-                       result = ISC_R_FAILURE;
-                       goto cleanup;
+                       return ISC_R_FAILURE;
                }
 
                (void) strncpy(to, tmp_str, tolen);
-
-               result = ISC_R_SUCCESS;
+               free(tmp_str);
+               return ISC_R_SUCCESS;
        } else {
                debug("libidn idna_to_ascii_8z failed: %s",
                      idna_strerror(res));
-               result = ISC_R_FAILURE;
        }
 
-cleanup:
-       free(tmp_str);
-       return (result);
+       return ISC_R_FAILURE;
 }
 
 static isc_result_t
@@ -4535,4 +4558,79 @@ cleanup:
        return (result);
 }
 #endif /* WITH_LIBIDN */
+
+#ifdef WITH_LIBIDN2
+/* Converts name from locale directly into ACE format, skip UTF-8 step */
+static isc_result_t
+libidn2_locale_to_utf8(const char *from, char *to, size_t tolen) {
+       int res;
+       char *tmp_str = NULL;
+
+       res = idn2_lookup_ul(from, &tmp_str, IDN2_NONTRANSITIONAL);
+       if (res == IDN2_DISALLOWED)
+               res = idn2_lookup_ul(from, &tmp_str, IDN2_TRANSITIONAL);
+
+       if (res == IDN2_OK) {
+               /* check the length */
+               if (strlen(tmp_str) >= tolen) {
+                       debug("ACE string is too long");
+                       free(tmp_str);
+                       return ISC_R_FAILURE;
+               }
+
+               (void) strncpy(to, tmp_str, tolen);
+               free(tmp_str);
+
+               return ISC_R_SUCCESS;
+       }
+
+       debug("libidn2 idn2_lookup_u8 failed: %s", idn2_strerror(res));
+       return ISC_R_FAILURE;
+}
+
+static isc_result_t
+libidn2_utf8_to_ace(const char *from, char *to, size_t tolen) {
+       int res;
+
+       /* Just check the format again. */
+       res = idn2_to_unicode_8zlz(from, NULL,
+                              IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);
+       if (res == IDN2_OK) {
+               strncpy(to, from, tolen);
+               return ISC_R_SUCCESS;
+       }
+       debug("libidn2 idn2_to_unicode_8zlz failed: %s", idn2_strerror(res));
+       if (res == IDN2_TOO_BIG_DOMAIN)
+               return ISC_R_NOSPACE;
+       else
+               return ISC_R_FAILURE;
+}
+
+static isc_result_t
+libidn2_ace_to_locale(const char *from, char *to, size_t tolen) {
+       int res;
+       char *tmp_str = NULL;
+
+       res = idn2_to_unicode_8zlz(from, &tmp_str,
+                              IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);
+
+       if (res == IDN2_OK) {
+               /* check the length */
+               if (strlen(tmp_str) >= tolen) {
+                       debug("encoded ASC string is too long");
+                       idn2_free(tmp_str);
+                       return ISC_R_FAILURE;
+               }
+
+               (void) strncpy(to, tmp_str, tolen);
+               free(tmp_str);
+               return ISC_R_SUCCESS;
+       } else {
+               debug("libidn idna_to_ascii_8z failed: %s",
+                     idn2_strerror(res));
+       }
+
+       return ISC_R_FAILURE;
+}
+#endif /* WITH_LIBIDN2 */
 #endif /* WITH_IDN_SUPPORT */
index f27b839c7b75102380c3a03fd6bc82481024d952..5aa242e105dd0d8e716e203f482204583319f25e 100644 (file)
@@ -721,7 +721,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
                            lookup->rdtype != dns_rdatatype_axfr)
                                lookup->rdtype = rdtype;
                        lookup->rdtypeset = ISC_TRUE;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
                        idnoptions = 0;
 #endif
                        if (rdtype == dns_rdatatype_axfr) {
@@ -736,7 +736,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
                        } else if (rdtype == dns_rdatatype_any) {
                                if (!lookup->tcp_mode_set)
                                        lookup->tcp_mode = ISC_TRUE;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
                        } else if (rdtype == dns_rdatatype_a ||
                                   rdtype == dns_rdatatype_aaaa ||
                                   rdtype == dns_rdatatype_mx) {
@@ -771,7 +771,7 @@ parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
                        if (!lookup->rdtypeset ||
                            lookup->rdtype != dns_rdatatype_axfr)
                                lookup->rdtype = dns_rdatatype_any;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
                        idnoptions = 0;
 #endif
                        list_type = dns_rdatatype_any;
@@ -885,7 +885,7 @@ main(int argc, char **argv) {
        ISC_LIST_INIT(search_list);
 
        fatalexit = 1;
-#ifdef WITH_IDN
+#ifdef WITH_IDNKIT
        idnoptions = IDN_ASCCHECK;
 #endif
 
index 228af0b4bcbff5e14220fc84495750de75451965..4c7b06b4b75fe211735de4670743d9eead744f33 100644 (file)
@@ -4701,8 +4701,8 @@ NOM_PATH_FILE(XSLT_DBLATEX_FASTBOOK, xsl/latex_book_fast.xsl, $dblatex_xsl_trees
 # IDN support using idnkit
 #
 AC_ARG_WITH(idnkit,
-           AS_HELP_STRING([--with-idn[=PREFIX]],
-                          [enable IDN support using idnkit [default PREFIX]]),
+           AS_HELP_STRING([--with-idn[=PATH]],
+                          [enable IDN support using idnkit idnkit yes|no|path]),
        use_idnkit="$withval", use_idnkit="no")
 case "$use_idnkit" in
 yes)
@@ -4777,7 +4777,7 @@ AC_SUBST(IDNKIT_LIBS)
 # IDN support using libidn
 #
 AC_ARG_WITH(libidn,
-       [  --with-libidn[=MPREFIX]   enable IDN support using GNU libidn [default PREFIX]],
+       [  --with-libidn[=PATH]   enable IDN support using GNU libidn yes|no|path],
        use_libidn="$withval", use_libidn="no")
 case "$use_libidn" in
 yes)
@@ -4802,17 +4802,53 @@ if test "$use_libidn" != no; then
 fi
 AC_SUBST(LIBIDN_LIBS)
 
+#
+# IDN support using libidn2
+#
+
+AC_ARG_WITH(libidn2,
+       [  --with-libidn2[=PATH]  enable IDN support using GNU libidn2 yes|no|path],
+       use_libidn2="$withval", use_libidn2="no")
+case "$use_libidn2" in
+yes)
+       if test X$prefix = XNONE ; then
+               libidn2_path=/usr/local
+       else
+               libidn2_path=$prefix
+       fi
+       ;;
+no)
+       ;;
+*)
+       libidn2_path="$use_libidn2"
+       ;;
+esac
+
+LIBIDN2_LIBS=
+if test "$use_libidn2" != no; then
+       AC_DEFINE(WITH_LIBIDN2, 1, [define if libidn2 support is to be included.])
+       STD_CINCLUDES="$STD_CINCLUDES -I$libidn2_path/include"
+       LIBIDN_LIBS="-lidn2"
+fi
+AC_SUBST(LIBIDN2_LIBS)
+
 #
 # IDN support in general
 #
 
-# check if idnkit and libidn are not used at the same time
+# check if idnkit, libidn and libidn2 are not used at the same time
 if test "$use_idnkit" != no && test "$use_libidn" != no; then
     AC_MSG_ERROR([idnkit and libidn cannot be used at the same time.])
 fi
+if test "$use_idnkit" != no && test "$use_libidn2" != no; then
+    AC_MSG_ERROR([idnkit and libidn2 cannot be used at the same time.])
+fi
+if test "$use_libidn" != no && test "$use_libidn2" != no; then
+    AC_MSG_ERROR([libidn and libidn2 cannot be used at the same time.])
+fi
 
 # the IDN support is on
-if test "$use_idnkit" != no || test "$use_libidn" != no; then
+if test "$use_idnkit" != no || test "$use_libidn" != no || test "$use_libidn2" != no; then
        AC_DEFINE(WITH_IDN_SUPPORT, 1, [define if IDN support is to be included.])
 fi