From ccfa6531ff7ae4eb3762679c5d8d3dffc072cc98 Mon Sep 17 00:00:00 2001 From: Petr Menšík Date: Mar 22 2018 15:12:12 +0000 Subject: Add dig support for libidn2 (#1098783) Signed-off-by: Petr Menšík --- diff --git a/bind-9.11-libidn2.patch b/bind-9.11-libidn2.patch new file mode 100644 index 0000000..6beab52 --- /dev/null +++ b/bind-9.11-libidn2.patch @@ -0,0 +1,1189 @@ +From 3dcf053c775344855bd6476ec4f4bada824cdd41 Mon Sep 17 00:00:00 2001 +From: Tomas Hozza +Date: Wed, 23 Sep 2015 14:37:16 +0200 +Subject: [PATCH] Add support for GNU libidn +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Added new configure option: +--with-libidn - to enable IDN using GNU libidn + +Renamed configure option: +--with-idn to --with-idnkit to make the option usage more clear + +idnkit and libidn support can not be used at the same time. + +Signed-off-by: Tomas Hozza +(cherry picked from commit 2320443f63b14ff926d0b91b479a48e29bc02376) +(cherry picked from commit edab22119f5d2b45a18727a6eb92f11b39ca3e73) + +Add support for libidn2 + +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 + +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 +(cherry picked from commit 505f673451d9f94488b99f5af0ea042e3f8e0915) +(cherry picked from commit 56b66f01c6ae4d9db3a2b8df29af21f43ed65516) + +Remove conversion from locale to utf8 from public API + +Emit fatal failures on locale to ACE encoding + +Separate idnout support, disable it for libidn2 < 2.0 + +Add custom path to libidn. Leave default path for multilib support. + +Allow turning off IDN input processing by dig option + +Improve documentation, fix support in host + +Fix configure changes to adjust help text + +Use strlcpy with size guard + +Improve IDN variants choosing. Fix idn2 function name. + +Remove immediate idn_locale_to_ace and idn_ace_to_locale. + +Signed-off-by: Petr Menšík +(cherry picked from commit 94757c1545259ec3d7d99f3ba7f9baa9ce58e0d3) +(cherry picked from commit 2b031d17592a253297545c6e525019706c17c460) + +Remove support for libidn (IDN 2003) + +Signed-off-by: Petr Menšík +(cherry picked from commit 8254cf69d34947713c99839dd5139f326d8e5d43) +(cherry picked from commit 9117bbe9a5d637d51ef11c71ff6743e027db5e9e) + +Sanitize IDN initialization + +Signed-off-by: Petr Menšík +(cherry picked from commit 29b94bbb04014681afe61c1594b99f6ec30f6b1f) +(cherry picked from commit 82914d0a416edb6667e94b54ae828cd0ca8f029b) + +Simplify the libidn2 configure checks + +(cherry picked from commit 76c05a71fcf464d6a638b2d8fab589100850e3f0) +(cherry picked from commit c08528682254506f4bcf8155d700eff3ce18b601) + +Add release notes for IDNA2008 + +(cherry picked from commit e7590c7528229c7bc761a6c69c33dfb69fbaf82f) +(cherry picked from commit 2ff3b664bca0c084326d2eaf75cb3b382fa26108) +--- + bin/dig/Makefile.in | 6 +- + bin/dig/dig.c | 27 +++- + bin/dig/dig.docbook | 18 ++- + bin/dig/dighost.c | 304 +++++++++++++++++++++++++++++----------------- + bin/dig/host.c | 10 +- + bin/dig/include/dig/dig.h | 3 +- + config.h.in | 11 +- + configure | 181 ++++++++++++++++++++++++--- + configure.in | 81 +++++++++--- + doc/arm/notes.xml | 15 +++ + 10 files changed, 491 insertions(+), 165 deletions(-) + +diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in +index 511fdfe86e..d8080e5b30 100644 +--- a/bin/dig/Makefile.in ++++ b/bin/dig/Makefile.in +@@ -16,7 +16,7 @@ READLINE_LIB = @READLINE_LIB@ + + CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} \ + ${BIND9_INCLUDES} ${ISC_INCLUDES} \ +- ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} @DST_OPENSSL_INC@ ++ ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} @LIBIDN2_CFLAGS@ @DST_OPENSSL_INC@ + + CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@ + CWARNINGS = +@@ -38,10 +38,10 @@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \ + ${ISCCFGDEPLIBS} ${LWRESDEPLIBS} + + LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ +- ${ISCLIBS} @IDNLIBS@ @LIBS@ ++ ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@ + + NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ +- ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ ++ ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@ + + SUBDIRS = + +diff --git a/bin/dig/dig.c b/bin/dig/dig.c +index 2e1ade8bf3..9a1176353e 100644 +--- a/bin/dig/dig.c ++++ b/bin/dig/dig.c +@@ -187,7 +187,8 @@ help(void) { + " +[no]fail (Don't try next server on SERVFAIL)\n" + " +[no]header-only (Send query without a question section)\n" + " +[no]identify (ID responders in short answers)\n" +-" +[no]idnout (convert IDN response)\n" ++" +[no]idnin (Parse IDN names)\n" ++" +[no]idnout (Convert IDN response)\n" + " +[no]ignore (Don't revert to TCP for TC responses.)\n" + " +[no]keepopen (Keep the TCP socket open between queries)\n" + " +[no]mapped (Allow mapped IPv4 over IPv6)\n" +@@ -1091,12 +1092,28 @@ plus_option(const char *option, isc_boolean_t is_batchfile, + lookup->identify = state; + break; + case 'n': +- FULLCHECK("idnout"); +-#ifndef WITH_IDN +- fprintf(stderr, ";; IDN support not enabled\n"); ++ switch (cmd[3]) { ++ case 'i': ++ FULLCHECK("idnin"); ++#ifndef WITH_IDN_SUPPORT ++ fprintf(stderr, ";; IDN input support" ++ " not enabled\n"); ++#else ++ lookup->idnin = state; ++#endif ++ break; ++ case 'o': ++ FULLCHECK("idnout"); ++#ifndef WITH_IDN_OUT_SUPPORT ++ fprintf(stderr, ";; IDN output support" ++ " not enabled\n"); + #else +- lookup->idnout = state; ++ lookup->idnout = state; + #endif ++ break; ++ default: ++ goto invalid_option; ++ } + break; + default: + goto invalid_option; +diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook +index bee62c6307..da5b7d6515 100644 +--- a/bin/dig/dig.docbook ++++ b/bin/dig/dig.docbook +@@ -773,6 +773,17 @@ + + + ++ ++ ++ ++ ++ Process [do not process] IDN domain names on input. ++ This requires IDN SUPPORT to have been enabled at ++ compile time. The default is to process IDN input. ++ ++ ++ ++ + + + +@@ -1265,10 +1276,9 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr + dig appropriately converts character encoding of + domain name before sending a request to DNS server or displaying a + reply from the server. +- If you'd like to turn off the IDN support for some reason, defines +- the IDN_DISABLE environment variable. +- The IDN support is disabled if the variable is set when +- dig runs. ++ If you'd like to turn off the IDN support for some reason, use ++ parameters +noidnin and ++ +noidnout. + + + +diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c +index fdfff399f5..c179b625f1 100644 +--- a/bin/dig/dighost.c ++++ b/bin/dig/dighost.c +@@ -21,18 +21,25 @@ + #include + #include + #include ++#include + + #ifdef HAVE_LOCALE_H + #include + #endif + +-#ifdef WITH_IDN ++#ifdef WITH_IDN_SUPPORT ++#ifdef WITH_IDNKIT + #include + #include + #include + #include + #endif + ++#ifdef WITH_LIBIDN2 ++#include ++#endif ++#endif /* WITH_IDN_SUPPORT */ ++ + #include + #ifdef DIG_SIGCHASE + #include +@@ -145,18 +152,26 @@ int lookup_counter = 0; + + static char servercookie[256]; + +-#ifdef WITH_IDN +-static void initialize_idn(void); +-static isc_result_t output_filter(isc_buffer_t *buffer, +- unsigned int used_org, +- isc_boolean_t absolute); +-static idn_result_t append_textname(char *name, const char *origin, +- size_t namesize); +-static void idn_check_result(idn_result_t r, const char *msg); +- +-#define MAXDLEN 256 +-int idnoptions = 0; ++#ifdef WITH_IDN_SUPPORT ++static void idn_initialize(void); ++static isc_result_t idn_locale_to_ace(const char *from, ++ char *to, ++ size_t tolen); ++#endif /* WITH_IDN_SUPPORT */ ++ ++#ifdef WITH_IDN_OUT_SUPPORT ++static isc_result_t idn_ace_to_locale(const char *from, ++ char *to, ++ size_t tolen); ++static isc_result_t output_filter(isc_buffer_t *buffer, ++ unsigned int used_org, ++ isc_boolean_t absolute); ++#define MAXDLEN 256 ++ ++#ifdef WITH_IDNKIT ++int idnoptions = 0; + #endif ++#endif /* WITH_IDN_OUT_SUPPORT */ + + isc_socket_t *keep = NULL; + isc_sockaddr_t keepaddr; +@@ -803,7 +818,12 @@ make_empty_lookup(void) { + looknew->sendcookie = ISC_FALSE; + looknew->seenbadcookie = ISC_FALSE; + looknew->badcookie = ISC_TRUE; +-#ifdef WITH_IDN ++#ifdef WITH_IDN_SUPPORT ++ looknew->idnin = ISC_TRUE; ++#else ++ looknew->idnin = ISC_FALSE; ++#endif ++#ifdef WITH_IDN_OUT_SUPPORT + looknew->idnout = ISC_TRUE; + #else + looknew->idnout = ISC_FALSE; +@@ -952,6 +972,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { + } + looknew->ednsneg = lookold->ednsneg; + looknew->mapped = lookold->mapped; ++ looknew->idnin = lookold->idnin; + looknew->idnout = lookold->idnout; + #ifdef DIG_SIGCHASE + looknew->sigchase = lookold->sigchase; +@@ -1512,8 +1533,19 @@ setup_system(isc_boolean_t ipv4only, isc_boolean_t ipv6only) { + copy_server_list(lwconf, &server_list); + } + +-#ifdef WITH_IDN +- initialize_idn(); ++#ifdef HAVE_SETLOCALE ++ /* Set locale */ ++ (void)setlocale(LC_ALL, ""); ++#endif ++ ++#ifdef WITH_IDN_SUPPORT ++ idn_initialize(); ++#endif ++ ++#ifdef WITH_IDN_OUT_SUPPORT ++ /* Set domain name -> text post-conversion filter. */ ++ result = dns_name_settotextfilter(output_filter); ++ check_result(result, "dns_name_settotextfilter"); + #endif + + if (keyfile[0] != 0) +@@ -2344,12 +2376,13 @@ setup_lookup(dig_lookup_t *lookup) { + char store[MXNAME]; + char ecsbuf[20]; + char cookiebuf[256]; +-#ifdef WITH_IDN +- idn_result_t mr; +- char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME]; ++ char *origin = NULL; ++ char *textname = NULL; ++#ifdef WITH_IDN_SUPPORT ++ char idn_origin[MXNAME], idn_textname[MXNAME]; + #endif + +-#ifdef WITH_IDN ++#ifdef WITH_IDN_OUT_SUPPORT + result = dns_name_settotextfilter(lookup->idnout ? + output_filter : NULL); + check_result(result, "dns_name_settotextfilter"); +@@ -2382,15 +2415,20 @@ setup_lookup(dig_lookup_t *lookup) { + isc_buffer_init(&lookup->onamebuf, lookup->oname_space, + sizeof(lookup->oname_space)); + +-#ifdef WITH_IDN + /* + * We cannot convert `textname' and `origin' separately. + * `textname' doesn't contain TLD, but local mapping needs + * TLD. + */ +- mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname, +- utf8_textname, sizeof(utf8_textname)); +- idn_check_result(mr, "convert textname to UTF-8"); ++ textname = lookup->textname; ++#ifdef WITH_IDN_SUPPORT ++ if (lookup->idnin) { ++ result = idn_locale_to_ace(lookup->textname, idn_textname, ++ sizeof(idn_textname)); ++ check_result(result, "convert textname to IDN encoding"); ++ debug("idn_textname: %s", idn_textname); ++ textname = idn_textname; ++ } + #endif + + /* +@@ -2401,17 +2439,8 @@ setup_lookup(dig_lookup_t *lookup) { + * is TRUE or we got a domain line in the resolv.conf file. + */ + if (lookup->new_search) { +-#ifdef WITH_IDN +- if ((count_dots(utf8_textname) >= ndots) || !usesearch) { +- lookup->origin = NULL; /* Force abs lookup */ +- lookup->done_as_is = ISC_TRUE; +- lookup->need_search = usesearch; +- } else if (lookup->origin == NULL && usesearch) { +- lookup->origin = ISC_LIST_HEAD(search_list); +- lookup->need_search = ISC_FALSE; +- } +-#else +- if ((count_dots(lookup->textname) >= ndots) || !usesearch) { ++ if ((count_dots(textname) >= ndots) || !usesearch) ++ { + lookup->origin = NULL; /* Force abs lookup */ + lookup->done_as_is = ISC_TRUE; + lookup->need_search = usesearch; +@@ -2419,24 +2448,8 @@ setup_lookup(dig_lookup_t *lookup) { + lookup->origin = ISC_LIST_HEAD(search_list); + lookup->need_search = ISC_FALSE; + } +-#endif + } + +-#ifdef WITH_IDN +- if (lookup->origin != NULL) { +- mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, +- lookup->origin->origin, utf8_origin, +- sizeof(utf8_origin)); +- idn_check_result(mr, "convert origin to UTF-8"); +- mr = append_textname(utf8_textname, utf8_origin, +- sizeof(utf8_textname)); +- idn_check_result(mr, "append origin to textname"); +- } +- mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP | +- IDN_IDNCONV | IDN_LENCHECK, utf8_textname, +- idn_textname, sizeof(idn_textname)); +- idn_check_result(mr, "convert UTF-8 textname to IDN encoding"); +-#else + if (lookup->origin != NULL) { + debug("trying origin %s", lookup->origin->origin); + result = dns_message_gettempname(lookup->sendmsg, +@@ -2444,8 +2457,18 @@ setup_lookup(dig_lookup_t *lookup) { + check_result(result, "dns_message_gettempname"); + dns_name_init(lookup->oname, NULL); + /* XXX Helper funct to conv char* to name? */ +- len = (unsigned int) strlen(lookup->origin->origin); +- isc_buffer_init(&b, lookup->origin->origin, len); ++ origin = lookup->origin->origin; ++#ifdef WITH_IDN_SUPPORT ++ if (lookup->idnin) { ++ result = idn_locale_to_ace(lookup->origin->origin, ++ idn_origin, sizeof(idn_origin)); ++ check_result(result, "convert origin to IDN encoding"); ++ debug("trying idn origin %s", idn_origin); ++ origin = idn_origin; ++ } ++#endif ++ len = (unsigned int) strlen(origin); ++ isc_buffer_init(&b, origin, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(lookup->oname, &b, dns_rootname, + 0, &lookup->onamebuf); +@@ -2455,7 +2478,7 @@ setup_lookup(dig_lookup_t *lookup) { + dns_message_puttempname(lookup->sendmsg, + &lookup->oname); + fatal("'%s' is not in legal name syntax (%s)", +- lookup->origin->origin, ++ origin, + isc_result_totext(result)); + } + if (lookup->trace && lookup->trace_root) { +@@ -2466,8 +2489,8 @@ setup_lookup(dig_lookup_t *lookup) { + + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); +- len = (unsigned int) strlen(lookup->textname); +- isc_buffer_init(&b, lookup->textname, len); ++ len = (unsigned int) strlen(textname); ++ isc_buffer_init(&b, textname, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(name, &b, NULL, 0, NULL); + if (result == ISC_R_SUCCESS && +@@ -2492,28 +2515,17 @@ setup_lookup(dig_lookup_t *lookup) { + } + } + dns_message_puttempname(lookup->sendmsg, &lookup->oname); +- } else +-#endif +- { ++ } else { + debug("using root origin"); + if (lookup->trace && lookup->trace_root) + dns_name_clone(dns_rootname, lookup->name); + else { +-#ifdef WITH_IDN +- len = (unsigned int) strlen(idn_textname); +- isc_buffer_init(&b, idn_textname, len); ++ len = (unsigned int) strlen(textname); ++ isc_buffer_init(&b, textname, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(lookup->name, &b, + dns_rootname, 0, + &lookup->namebuf); +-#else +- len = (unsigned int) strlen(lookup->textname); +- isc_buffer_init(&b, lookup->textname, len); +- isc_buffer_add(&b, len); +- result = dns_name_fromtext(lookup->name, &b, +- dns_rootname, 0, +- &lookup->namebuf); +-#endif + } + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(lookup->sendmsg, +@@ -4512,7 +4524,7 @@ destroy_libs(void) { + void * ptr; + dig_message_t *chase_msg; + #endif +-#ifdef WITH_IDN ++#ifdef WITH_IDN_SUPPORT + isc_result_t result; + #endif + +@@ -4549,7 +4561,7 @@ destroy_libs(void) { + + clear_searchlist(); + +-#ifdef WITH_IDN ++#ifdef WITH_IDN_SUPPORT + result = dns_name_settotextfilter(NULL); + check_result(result, "dns_name_settotextfilter"); + #endif +@@ -4633,27 +4645,7 @@ destroy_libs(void) { + isc_mem_destroy(&mctx); + } + +-#ifdef WITH_IDN +-static void +-initialize_idn(void) { +- idn_result_t r; +- isc_result_t result; +- +-#ifdef HAVE_SETLOCALE +- /* Set locale */ +- (void)setlocale(LC_ALL, ""); +-#endif +- /* Create configuration context. */ +- r = idn_nameinit(1); +- if (r != idn_success) +- fatal("idn api initialization failed: %s", +- idn_result_tostring(r)); +- +- /* Set domain name -> text post-conversion filter. */ +- result = dns_name_settotextfilter(output_filter); +- check_result(result, "dns_name_settotextfilter"); +-} +- ++#ifdef WITH_IDN_OUT_SUPPORT + static isc_result_t + output_filter(isc_buffer_t *buffer, unsigned int used_org, + isc_boolean_t absolute) +@@ -4661,6 +4653,7 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org, + char tmp1[MAXDLEN], tmp2[MAXDLEN]; + size_t fromlen, tolen; + isc_boolean_t end_with_dot; ++ isc_result_t result; + + /* + * Copy contents of 'buffer' to 'tmp1', supply trailing dot +@@ -4669,6 +4662,7 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org, + fromlen = isc_buffer_usedlength(buffer) - used_org; + if (fromlen >= MAXDLEN) + return (ISC_R_SUCCESS); ++ + memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen); + end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE; + if (absolute && !end_with_dot) { +@@ -4677,13 +4671,16 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org, + return (ISC_R_SUCCESS); + tmp1[fromlen - 1] = '.'; + } ++ + tmp1[fromlen] = '\0'; + + /* + * Convert contents of 'tmp1' to local encoding. + */ +- if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success) ++ result = idn_ace_to_locale(tmp1, tmp2, sizeof(tmp2)); ++ if (result != ISC_R_SUCCESS) { + return (ISC_R_SUCCESS); ++ } + strlcpy(tmp1, tmp2, MAXDLEN); + + /* +@@ -4703,35 +4700,118 @@ output_filter(isc_buffer_t *buffer, unsigned int used_org, + + return (ISC_R_SUCCESS); + } ++#endif + +-static idn_result_t +-append_textname(char *name, const char *origin, size_t namesize) { +- size_t namelen = strlen(name); +- size_t originlen = strlen(origin); ++#ifdef WITH_IDN_SUPPORT ++#ifdef WITH_IDNKIT ++static void ++idnkit_check_result(idn_result_t result, const char *msg) { ++ if (result != idn_success) { ++ fatal("%s: %s", msg, idn_result_tostring(result)); ++ } ++} ++ ++static void ++idn_initialize(void) { ++ idn_result_t result; + +- /* Already absolute? */ +- if (namelen > 0 && name[namelen - 1] == '.') +- return (idn_success); ++ /* Create configuration context. */ ++ result = idn_nameinit(1); ++ idnkit_check_result(result, "idnkit api initialization failed"); ++ return (ISC_R_SUCCESS); ++} + +- /* Append dot and origin */ ++static isc_result_t ++idn_locale_to_ace(const char *from, char *to, size_t tolen) { ++ char utf8_textname[MXNAME]; ++ idn_result_t result; ++ ++ result = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, from, ++ utf8_textname, sizeof(utf8_textname)); ++ idnkit_check_result(result, "idnkit idn_encodename to utf8 failed"); ++ ++ result = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP | ++ IDN_IDNCONV | IDN_LENCHECK, ++ utf8_textname, to, tolen); ++ idnkit_check_result(result, "idnkit idn_encodename to idn failed"); ++ return (ISC_R_SUCCESS); ++} + +- if (namelen + 1 + originlen >= namesize) +- return (idn_buffer_overflow); ++static isc_result_t ++idn_ace_to_locale(const char *from, char *to, size_t tolen) { ++ idn_result_t result; + +- if (*origin != '.') +- name[namelen++] = '.'; +- (void)strlcpy(name + namelen, origin, namesize - namelen); +- return (idn_success); ++ result = idn_decodename(IDN_DECODE_APP, from, to, tolen); ++ if (result != idn_success) { ++ debug("idnkit idn_decodename failed: %s", ++ idn_result_tostring(result)); ++ return (ISC_R_FAILURE); ++ } ++ return (ISC_R_SUCCESS); + } ++#endif /* WITH_IDNKIT */ + ++#ifdef WITH_LIBIDN2 + static void +-idn_check_result(idn_result_t r, const char *msg) { +- if (r != idn_success) { +- exitcode = 1; +- fatal("%s: %s", msg, idn_result_tostring(r)); ++idn_initialize(void) { ++} ++ ++static isc_result_t ++idn_locale_to_ace(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"); ++ idn2_free(tmp_str); ++ return ISC_R_NOSPACE; ++ } ++ ++ (void) strlcpy(to, tmp_str, tolen); ++ idn2_free(tmp_str); ++ return ISC_R_SUCCESS; + } ++ ++ fatal("idn2_lookup_ul failed: %s", idn2_strerror(res)); ++ return ISC_R_FAILURE; ++} ++ ++#ifdef WITH_IDN_OUT_SUPPORT ++static isc_result_t ++idn_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("idn2_to_unicode_8zlz failed: %s", ++ idn2_strerror(res)); ++ } ++ ++ return ISC_R_FAILURE; + } +-#endif /* WITH_IDN */ ++#endif /* WITH_IDN_OUT_SUPPORT */ ++#endif /* WITH_LIBIDN2 */ ++#endif /* WITH_IDN_SUPPORT */ + + #ifdef DIG_SIGCHASE + void +diff --git a/bin/dig/host.c b/bin/dig/host.c +index f9e5b08962..f16483827a 100644 +--- a/bin/dig/host.c ++++ b/bin/dig/host.c +@@ -16,7 +16,7 @@ + #include + #endif + +-#ifdef WITH_IDN ++#ifdef WITH_IDNKIT + #include + #include + #include +@@ -720,7 +720,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) { +@@ -735,7 +735,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) { +@@ -767,7 +767,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; +@@ -881,7 +881,7 @@ main(int argc, char **argv) { + ISC_LIST_INIT(search_list); + + fatalexit = 1; +-#ifdef WITH_IDN ++#ifdef WITH_IDNKIT + idnoptions = IDN_ASCCHECK; + #endif + +diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h +index 2c7a5aeaa8..446ee027af 100644 +--- a/bin/dig/include/dig/dig.h ++++ b/bin/dig/include/dig/dig.h +@@ -130,6 +130,7 @@ struct dig_lookup { + ednsneg, + mapped, + print_unknown_format, ++ idnin, + idnout; + #ifdef DIG_SIGCHASE + isc_boolean_t sigchase; +@@ -292,7 +293,7 @@ extern char *progname; + extern int tries; + extern int fatalexit; + extern isc_boolean_t verbose; +-#ifdef WITH_IDN ++#ifdef WITH_IDNKIT + extern int idnoptions; + #endif + +diff --git a/config.h.in b/config.h.in +index 29cdb07a50..cd798c288d 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -596,7 +596,16 @@ int sigwait(const unsigned int *set, int *sig); + #undef WANT_QUERYTRACE + + /* define if idnkit support is to be included. */ +-#undef WITH_IDN ++#undef WITH_IDNKIT ++ ++/* define if IDN output support is to be included. */ ++#undef WITH_IDN_OUT_SUPPORT ++ ++/* define if IDN input support is to be included. */ ++#undef WITH_IDN_SUPPORT ++ ++/* define if libidn2 support is to be included. */ ++#undef WITH_LIBIDN2 + + /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +diff --git a/configure b/configure +index 5ae413202f..ce9f393170 100755 +--- a/configure ++++ b/configure +@@ -682,7 +682,9 @@ UNITTESTS + ATFLIBS + ATFBIN + ATFBUILD +-IDNLIBS ++LIBIDN2_LIBS ++LIBIDN2_CFLAGS ++IDNKIT_LIBS + XSLT_DBLATEX_FASTBOOK + XSLT_DBLATEX_STYLE + XSLT_DOCBOOK_MAKETOC_XHTML +@@ -1066,10 +1068,11 @@ enable_dnstap + with_protobuf_c + with_libfstrm + with_docbook_xsl +-with_idn ++with_idnkit + with_libiconv + with_iconv + with_idnlib ++with_libidn2 + with_atf + with_tuning + enable_querytrace +@@ -1794,10 +1797,11 @@ Optional Packages: + --with-protobuf-c=path Path where protobuf-c is installed, for dnstap + --with-libfstrm=path Path where libfstrm is installed, for dnstap + --with-docbook-xsl=PATH specify path for Docbook-XSL stylesheets +- --with-idn=MPREFIX enable IDN support using idnkit [default PREFIX] ++ --with-idnkit=PATH enable IDN support using idnkit [yes|no|path] + --with-libiconv=IPREFIX GNU libiconv are in IPREFIX [default PREFIX] + --with-iconv=LIBSPEC specify iconv library [default -liconv] + --with-idnlib=ARG specify libidnkit ++ --with-libidn2=PATH enable IDN support using GNU libidn2 [yes|no|path] + --with-atf support Automated Test Framework + --with-tuning=ARG Specify server tuning (large or default) + --with-dlopen=ARG support dynamically loadable DLZ drivers +@@ -22755,28 +22759,28 @@ fi + + + # +-# IDN support ++# IDN support using idnkit + # + +-# Check whether --with-idn was given. +-if test "${with_idn+set}" = set; then : +- withval=$with_idn; use_idn="$withval" ++# Check whether --with-idnkit was given. ++if test "${with_idnkit+set}" = set; then : ++ withval=$with_idnkit; use_idnkit="$withval" + else +- use_idn="no" ++ use_idnkit="no" + fi + +-case "$use_idn" in ++case "$use_idnkit" in + yes) + if test X$prefix = XNONE ; then +- idn_path=/usr/local ++ idnkit_path=/usr/local + else +- idn_path=$prefix ++ idnkit_path=$prefix + fi + ;; + no) + ;; + *) +- idn_path="$use_idn" ++ idnkit_path="$use_idnkit" + ;; + esac + +@@ -22833,20 +22837,161 @@ if test "yes" = "$idnlib"; then + as_fn_error $? "You must specify ARG for --with-idnlib." "$LINENO" 5 + fi + +-IDNLIBS= +-if test "no" != "$use_idn"; then ++IDNKIT_LIBS= ++if test "no" != "$use_idnkit"; then + +-$as_echo "#define WITH_IDN 1" >>confdefs.h ++$as_echo "#define WITH_IDNKIT 1" >>confdefs.h + +- STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include" ++ STD_CINCLUDES="$STD_CINCLUDES -I$idnkit_path/include" + if test "no" != "$idnlib"; then +- IDNLIBS="$idnlib $iconvlib" ++ IDNKIT_LIBS="$idnlib $iconvlib" + else +- IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib" ++ IDNKIT_LIBS="-L$idnkit_path/lib -lidnkit $iconvlib" + fi + fi + + ++# ++# IDN support using libidn2 ++# ++ ++LIBIDN2_CFLAGS= ++LIBIDN2_LIBS= ++ ++# Check whether --with-libidn2 was given. ++if test "${with_libidn2+set}" = set; then : ++ withval=$with_libidn2; use_libidn2="$withval" ++else ++ use_libidn2="no" ++fi ++ ++case $use_libidn2 in #( ++ no) : ++ : ;; #( ++ yes) : ++ ++ LIBIDN2_LIBS="-lidn2" ++ ;; #( ++ *) : ++ ++ LIBIDN2_CFLAGS="-I$use_libidn2/include" ++ LIBIDN2_LIBS="-L$use_libidn2/lib -lidn2" ++ ;; #( ++ *) : ++ ;; ++esac ++ ++if test "$use_libidn2" != "no"; then : ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing idn2_to_ascii_8z" >&5 ++$as_echo_n "checking for library containing idn2_to_ascii_8z... " >&6; } ++if ${ac_cv_search_idn2_to_ascii_8z+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_func_search_save_LIBS=$LIBS ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char idn2_to_ascii_8z (); ++int ++main () ++{ ++return idn2_to_ascii_8z (); ++ ; ++ return 0; ++} ++_ACEOF ++for ac_lib in '' idn2; do ++ if test -z "$ac_lib"; then ++ ac_res="none required" ++ else ++ ac_res=-l$ac_lib ++ LIBS="-l$ac_lib $ac_func_search_save_LIBS" ++ fi ++ if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_search_idn2_to_ascii_8z=$ac_res ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext ++ if ${ac_cv_search_idn2_to_ascii_8z+:} false; then : ++ break ++fi ++done ++if ${ac_cv_search_idn2_to_ascii_8z+:} false; then : ++ ++else ++ ac_cv_search_idn2_to_ascii_8z=no ++fi ++rm conftest.$ac_ext ++LIBS=$ac_func_search_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_idn2_to_ascii_8z" >&5 ++$as_echo "$ac_cv_search_idn2_to_ascii_8z" >&6; } ++ac_res=$ac_cv_search_idn2_to_ascii_8z ++if test "$ac_res" != no; then : ++ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ++ ++$as_echo "#define WITH_LIBIDN2 1" >>confdefs.h ++ ++else ++ as_fn_error $? "libidn2 requested, but not found" "$LINENO" 5 ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libidn2 supports idn2_to_unicode_8zlz" >&5 ++$as_echo_n "checking whether libidn2 supports idn2_to_unicode_8zlz... " >&6; } ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include ++int ++main () ++{ ++idn2_to_unicode_8zlz(".", NULL, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 ++$as_echo "yes" >&6; } ++ ++$as_echo "#define WITH_IDN_OUT_SUPPORT 1" >>confdefs.h ++ ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ ++fi ++ ++ ++ ++# ++# IDN support in general ++# ++ ++# check if idnkit and libidn2 are not used at the same time ++if test "$use_idnkit" != no && test "$use_libidn2" != no; then ++ as_fn_error $? "idnkit and libidn2 cannot be used at the same time." "$LINENO" 5 ++fi ++# the IDN support is on ++if test "$use_idnkit" != no || test "$use_libidn2" != no; then ++ ++$as_echo "#define WITH_IDN_SUPPORT 1" >>confdefs.h ++ ++ if test "$use_libidn2" = no || test "$use_libidn2_out" != no; then ++ ++$as_echo "#define WITH_IDN_OUT_SUPPORT 1" >>confdefs.h ++ ++ fi ++fi ++ + # + # Check whether to build Automated Test Framework unit tests + # +diff --git a/configure.in b/configure.in +index 388356a7c3..63988c97dc 100644 +--- a/configure.in ++++ b/configure.in +@@ -4824,24 +4824,24 @@ NOM_PATH_FILE(XSLT_DBLATEX_STYLE, xsl/docbook.xsl, $dblatex_xsl_trees) + NOM_PATH_FILE(XSLT_DBLATEX_FASTBOOK, xsl/latex_book_fast.xsl, $dblatex_xsl_trees) + + # +-# IDN support ++# IDN support using idnkit + # +-AC_ARG_WITH(idn, +- AS_HELP_STRING([--with-idn[=MPREFIX]], +- [enable IDN support using idnkit [default PREFIX]]), +- use_idn="$withval", use_idn="no") +-case "$use_idn" in ++AC_ARG_WITH(idnkit, ++ AS_HELP_STRING([--with-idnkit[=PATH]], ++ [enable IDN support using idnkit [yes|no|path]]), ++ use_idnkit="$withval", use_idnkit="no") ++case "$use_idnkit" in + yes) + if test X$prefix = XNONE ; then +- idn_path=/usr/local ++ idnkit_path=/usr/local + else +- idn_path=$prefix ++ idnkit_path=$prefix + fi + ;; + no) + ;; + *) +- idn_path="$use_idn" ++ idnkit_path="$use_idnkit" + ;; + esac + +@@ -4887,17 +4887,66 @@ if test "yes" = "$idnlib"; then + AC_MSG_ERROR([You must specify ARG for --with-idnlib.]) + fi + +-IDNLIBS= +-if test "no" != "$use_idn"; then +- AC_DEFINE(WITH_IDN, 1, [define if idnkit support is to be included.]) +- STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include" ++IDNKIT_LIBS= ++if test "no" != "$use_idnkit"; then ++ AC_DEFINE(WITH_IDNKIT, 1, [define if idnkit support is to be included.]) ++ STD_CINCLUDES="$STD_CINCLUDES -I$idnkit_path/include" + if test "no" != "$idnlib"; then +- IDNLIBS="$idnlib $iconvlib" ++ IDNKIT_LIBS="$idnlib $iconvlib" + else +- IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib" ++ IDNKIT_LIBS="-L$idnkit_path/lib -lidnkit $iconvlib" ++ fi ++fi ++AC_SUBST(IDNKIT_LIBS) ++ ++# ++# IDN support using libidn2 ++# ++ ++LIBIDN2_CFLAGS= ++LIBIDN2_LIBS= ++AC_ARG_WITH(libidn2, ++ AS_HELP_STRING([--with-libidn2[=PATH]], [enable IDN support using GNU libidn2 [yes|no|path]]), ++ use_libidn2="$withval", use_libidn2="no") ++AS_CASE([$use_libidn2], ++ [no],[:], ++ [yes],[ ++ LIBIDN2_LIBS="-lidn2" ++ ], ++ [*],[ ++ LIBIDN2_CFLAGS="-I$use_libidn2/include" ++ LIBIDN2_LIBS="-L$use_libidn2/lib -lidn2" ++ ]) ++ ++AS_IF([test "$use_libidn2" != "no"], ++ [AC_SEARCH_LIBS([idn2_to_ascii_8z], [idn2], ++ [AC_DEFINE(WITH_LIBIDN2, 1, [define if libidn2 support is to be included.])], ++ [AC_MSG_ERROR([libidn2 requested, but not found])]) ++ AC_MSG_CHECKING(whether libidn2 supports idn2_to_unicode_8zlz) ++ AC_TRY_LINK([#include ], ++ [idn2_to_unicode_8zlz(".", NULL, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);], ++ [AC_MSG_RESULT(yes) ++ AC_DEFINE(WITH_IDN_OUT_SUPPORT, 1, [define if IDN output support is to be included.])], ++ [AC_MSG_RESULT([no])]) ++ ]) ++AC_SUBST([LIBIDN2_CFLAGS]) ++AC_SUBST([LIBIDN2_LIBS]) ++ ++# ++# IDN support in general ++# ++ ++# check if idnkit and libidn2 are not used at the same time ++if test "$use_idnkit" != no && test "$use_libidn2" != no; then ++ AC_MSG_ERROR([idnkit and libidn2 cannot be used at the same time.]) ++fi ++# the IDN support is on ++if test "$use_idnkit" != no || test "$use_libidn2" != no; then ++ AC_DEFINE(WITH_IDN_SUPPORT, 1, [define if IDN input support is to be included.]) ++ if test "$use_libidn2" = no || test "$use_libidn2_out" != no; then ++ AC_DEFINE(WITH_IDN_OUT_SUPPORT, 1, [define if IDN output support is to be included.]) + fi + fi +-AC_SUBST(IDNLIBS) + + # + # Check whether to build Automated Test Framework unit tests +diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml +index ec761018c8..ea9b61fd73 100644 +--- a/doc/arm/notes.xml ++++ b/doc/arm/notes.xml +@@ -166,6 +166,14 @@ + [RT #43670] + + ++ ++ ++ named will now log a warning if the old ++ BIND now can be compiled against libidn2 library to add ++ IDNA2008 support. Previously BIND only supported IDNA2003 ++ using (now obsolete) idnkit-1 library. ++ ++ + + + +@@ -242,6 +250,13 @@ + Multicast DNS. [RT #44783] + + ++ ++ ++ dig +noidnin can be used to disable IDN ++ processing on the input domain name, when BIND is compiled ++ with IDN support. ++ ++ + + + +-- +2.14.3 + diff --git a/bind-99-libidn.patch b/bind-99-libidn.patch deleted file mode 100644 index 6e042be..0000000 --- a/bind-99-libidn.patch +++ /dev/null @@ -1,297 +0,0 @@ -diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in -index bd219c5..f71685b 100644 ---- a/bin/dig/Makefile.in -+++ b/bin/dig/Makefile.in -@@ -38,10 +38,10 @@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \ - ${ISCCFGDEPLIBS} ${LWRESDEPLIBS} - - LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -- ${ISCLIBS} @IDNLIBS@ @LIBS@ -+ ${ISCLIBS} @IDNLIBS@ @LIBS@ -lidn - - NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -- ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ -+ ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ -lidn - - SUBDIRS = - -@@ -59,6 +59,8 @@ HTMLPAGES = dig.html host.html nslookup.html - - MANOBJS = ${MANPAGES} ${HTMLPAGES} - -+EXT_CFLAGS = -DWITH_LIBIDN -+ - @BIND9_MAKE_RULES@ - - dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} -diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook -index 7a7e8e4..b36047f 100644 ---- a/bin/dig/dig.docbook -+++ b/bin/dig/dig.docbook -@@ -1251,8 +1251,8 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr - dig appropriately converts character encoding of - domain name before sending a request to DNS server or displaying a - reply from the server. -- If you'd like to turn off the IDN support for some reason, defines -- the IDN_DISABLE environment variable. -+ If you'd like to turn off the IDN support for some reason, define -+ the CHARSET=ASCII environment variable. - The IDN support is disabled if the variable is set when - dig runs. - -diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c -index 1f8bcf2..f657c30 100644 ---- a/bin/dig/dighost.c -+++ b/bin/dig/dighost.c -@@ -33,6 +33,11 @@ - #include - #endif - -+#ifdef WITH_LIBIDN -+#include -+#include -+#endif -+ - #include - #ifdef DIG_SIGCHASE - #include -@@ -158,6 +163,14 @@ static void idn_check_result(idn_result_t r, const char *msg); - int idnoptions = 0; - #endif - -+#ifdef WITH_LIBIDN -+static isc_result_t libidn_locale_to_utf8 (const char* from, char *to); -+static isc_result_t libidn_utf8_to_ascii (const char* from, char *to); -+static isc_result_t output_filter (isc_buffer_t *buffer, -+ unsigned int used_org, -+ isc_boolean_t absolute); -+#endif -+ - isc_socket_t *keep = NULL; - isc_sockaddr_t keepaddr; - -@@ -1448,8 +1461,15 @@ setup_system(isc_boolean_t ipv4only, isc_boolean_t ipv6only) { - - #ifdef WITH_IDN - initialize_idn(); -+ -+#endif -+#ifdef WITH_LIBIDN -+ result = dns_name_settotextfilter(output_filter); -+ check_result(result, "dns_name_settotextfilter"); -+#ifdef HAVE_SETLOCALE -+ setlocale (LC_ALL, ""); -+#endif - #endif -- - if (keyfile[0] != 0) - setup_file_key(); - else if (keysecret[0] != 0) -@@ -2231,8 +2251,11 @@ setup_lookup(dig_lookup_t *lookup) { - idn_result_t mr; - char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME]; - #endif -+#ifdef WITH_LIBIDN -+ char utf8_str[MXNAME], utf8_name[MXNAME], ascii_name[MXNAME]; -+#endif - --#ifdef WITH_IDN -+#if defined (WITH_IDN) || defined (WITH_LIBIDN) - result = dns_name_settotextfilter(lookup->idnout ? - output_filter : NULL); - check_result(result, "dns_name_settotextfilter"); -@@ -2274,6 +2297,14 @@ setup_lookup(dig_lookup_t *lookup) { - mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname, - utf8_textname, sizeof(utf8_textname)); - idn_check_result(mr, "convert textname to UTF-8"); -+#elif defined (WITH_LIBIDN) -+ result = libidn_locale_to_utf8 (lookup->textname, utf8_str); -+ check_result (result, "convert textname to UTF-8"); -+ len = strlen (utf8_str); -+ if (len < MXNAME) -+ (void) strcpy (utf8_name, utf8_str); -+ else -+ fatal ("Too long name"); - #endif - - /* -@@ -2286,15 +2317,11 @@ setup_lookup(dig_lookup_t *lookup) { - if (lookup->new_search) { - #ifdef WITH_IDN - if ((count_dots(utf8_textname) >= ndots) || !usesearch) { -- lookup->origin = NULL; /* Force abs lookup */ -- lookup->done_as_is = ISC_TRUE; -- lookup->need_search = usesearch; -- } else if (lookup->origin == NULL && usesearch) { -- lookup->origin = ISC_LIST_HEAD(search_list); -- lookup->need_search = ISC_FALSE; -- } -+#elif defined (WITH_LIBIDN) -+ if ((count_dots(utf8_name) >= ndots) || !usesearch) { - #else - if ((count_dots(lookup->textname) >= ndots) || !usesearch) { -+#endif - lookup->origin = NULL; /* Force abs lookup */ - lookup->done_as_is = ISC_TRUE; - lookup->need_search = usesearch; -@@ -2302,7 +2329,6 @@ setup_lookup(dig_lookup_t *lookup) { - lookup->origin = ISC_LIST_HEAD(search_list); - lookup->need_search = ISC_FALSE; - } --#endif - } - - #ifdef WITH_IDN -@@ -2319,6 +2345,20 @@ setup_lookup(dig_lookup_t *lookup) { - IDN_IDNCONV | IDN_LENCHECK, utf8_textname, - idn_textname, sizeof(idn_textname)); - idn_check_result(mr, "convert UTF-8 textname to IDN encoding"); -+#elif defined (WITH_LIBIDN) -+ if (lookup->origin != NULL) { -+ result = libidn_locale_to_utf8 (lookup->origin->origin, utf8_str); -+ check_result (result, "convert origin to UTF-8"); -+ if (len > 0 && utf8_name[len - 1] != '.') { -+ utf8_name[len++] = '.'; -+ if (len + strlen (utf8_str) < MXNAME) -+ (void) strcpy (utf8_name + len, utf8_str); -+ else -+ fatal ("Too long name + origin"); -+ } -+ } -+ -+ result = libidn_utf8_to_ascii (utf8_name, ascii_name); - #else - if (lookup->origin != NULL) { - debug("trying origin %s", lookup->origin->origin); -@@ -2389,6 +2429,13 @@ setup_lookup(dig_lookup_t *lookup) { - result = dns_name_fromtext(lookup->name, &b, - dns_rootname, 0, - &lookup->namebuf); -+#elif defined (WITH_LIBIDN) -+ len = strlen (ascii_name); -+ isc_buffer_init(&b, ascii_name, len); -+ isc_buffer_add(&b, len); -+ result = dns_name_fromtext(lookup->name, &b, -+ dns_rootname, 0, -+ &lookup->namebuf); - #else - len = (unsigned int) strlen(lookup->textname); - isc_buffer_init(&b, lookup->textname, len); -@@ -4377,7 +4424,7 @@ destroy_libs(void) { - void * ptr; - dig_message_t *chase_msg; - #endif --#ifdef WITH_IDN -+#if defined (WITH_IDN) || defined (WITH_LIBIDN) - isc_result_t result; - #endif - -@@ -4418,6 +4465,10 @@ destroy_libs(void) { - result = dns_name_settotextfilter(NULL); - check_result(result, "dns_name_settotextfilter"); - #endif -+#ifdef WITH_LIBIDN -+ result = dns_name_settotextfilter (NULL); -+ check_result(result, "clearing dns_name_settotextfilter"); -+#endif - dns_name_destroy(); - - if (commctx != NULL) { -@@ -4603,6 +4654,97 @@ idn_check_result(idn_result_t r, const char *msg) { - } - } - #endif /* WITH_IDN */ -+#ifdef WITH_LIBIDN -+static isc_result_t -+libidn_locale_to_utf8 (const char *from, char *to) { -+ char *utf8_str; -+ -+ debug ("libidn_locale_to_utf8"); -+ utf8_str = stringprep_locale_to_utf8 (from); -+ if (utf8_str != NULL) { -+ (void) strcpy (to, utf8_str); -+ free (utf8_str); -+ return ISC_R_SUCCESS; -+ } -+ -+ debug ("libidn_locale_to_utf8: failure"); -+ return ISC_R_FAILURE; -+} -+static isc_result_t -+libidn_utf8_to_ascii (const char *from, char *to) { -+ char *ascii; -+ int iresult; -+ -+ debug ("libidn_utf8_to_ascii"); -+ iresult = idna_to_ascii_8z (from, &ascii, 0); -+ if (iresult != IDNA_SUCCESS) { -+ debug ("idna_to_ascii_8z: %s", idna_strerror (iresult)); -+ return ISC_R_FAILURE; -+ } -+ -+ (void) strcpy (to, ascii); -+ free (ascii); -+ return ISC_R_SUCCESS; -+} -+ -+static isc_result_t -+output_filter (isc_buffer_t *buffer, unsigned int used_org, -+ isc_boolean_t absolute) { -+ -+ char tmp1[MXNAME], *tmp2; -+ size_t fromlen, tolen; -+ isc_boolean_t end_with_dot; -+ int iresult; -+ -+ debug ("output_filter"); -+ -+ fromlen = isc_buffer_usedlength (buffer) - used_org; -+ if (fromlen >= MXNAME) -+ return ISC_R_SUCCESS; -+ memcpy (tmp1, (char *) isc_buffer_base (buffer) + used_org, fromlen); -+ end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE; -+ if (absolute && !end_with_dot) { -+ fromlen++; -+ if (fromlen >= MXNAME) -+ return ISC_R_SUCCESS; -+ tmp1[fromlen - 1] = '.'; -+ } -+ tmp1[fromlen] = '\0'; -+ -+ iresult = idna_to_unicode_8z8z (tmp1, &tmp2, 0); -+ if (iresult != IDNA_SUCCESS) { -+ debug ("output_filter: %s", idna_strerror (iresult)); -+ return ISC_R_SUCCESS; -+ } -+ -+ (void) strcpy (tmp1, tmp2); -+ free (tmp2); -+ -+ tmp2 = stringprep_utf8_to_locale (tmp1); -+ if (tmp2 == NULL) { -+ debug ("output_filter: stringprep_utf8_to_locale failed"); -+ return ISC_R_SUCCESS; -+ } -+ -+ (void) strcpy (tmp1, tmp2); -+ free (tmp2); -+ -+ tolen = strlen (tmp1); -+ if (absolute && !end_with_dot && tmp1[tolen - 1] == '.') -+ tolen--; -+ -+ if (isc_buffer_length (buffer) < used_org + tolen) -+ return ISC_R_NOSPACE; -+ -+ debug ("%s", tmp1); -+ -+ isc_buffer_subtract (buffer, isc_buffer_usedlength (buffer) - used_org); -+ memcpy (isc_buffer_used (buffer), tmp1, tolen); -+ isc_buffer_add (buffer, tolen); -+ -+ return ISC_R_SUCCESS; -+} -+#endif /* WITH_LIBIDN*/ - - #ifdef DIG_SIGCHASE - void diff --git a/bind.spec b/bind.spec index 85f7992..9da4a05 100644 --- a/bind.spec +++ b/bind.spec @@ -89,8 +89,8 @@ Patch12: bind-9.10-sdb.patch # needs inpection Patch17: bind-9.3.2b1-fix_sdb_ldap.patch -# [ISC-Bugs #36101] IDN support in host/dig/nslookup using GNU libidn(2) -Patch73: bind-99-libidn.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1098783 +Patch73: bind-9.11-libidn2.patch Requires(post): systemd @@ -1025,6 +1025,7 @@ rm -rf ${RPM_BUILD_ROOT} %changelog * Wed Mar 21 2018 Petr Menšík - 32:9.11.3-2 - Rebase to 9.11.3 +- Add dig support for libidn2 (#1098783) * Thu Feb 15 2018 Petr Menšík - 32:9.11.3-1.b1 - Rebase to 9.11.3b1