diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 49143e581b..fd3e2d4013 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -235,10 +235,8 @@ help(void) { " +[no]identify (ID responders in short " "answers)\n" #ifdef HAVE_LIBIDN2 - " +[no]idnin (Parse IDN names " - "[default=on on tty])\n" - " +[no]idnout (Convert IDN response " - "[default=on on tty])\n" + " +[no]idn (convert international " + "domain names)\n" #endif /* ifdef HAVE_LIBIDN2 */ " +[no]ignore (Don't revert to TCP for " "TC responses.)\n" @@ -1615,7 +1613,7 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, break; case 'i': switch (cmd[1]) { - case 'd': /* identify */ + case 'd': switch (cmd[2]) { case 'e': FULLCHECK("identify"); @@ -1623,33 +1621,28 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, break; case 'n': switch (cmd[3]) { - case 'i': - FULLCHECK("idnin"); -#ifndef HAVE_LIBIDN2 - if (state) { - fprintf(stderr, - ";; IDN input support" - " not enabled\n"); - } -#else /* ifndef HAVE_LIBIDN2 */ + case '\0': + FULLCHECK("idn"); lookup->idnin = state; -#endif /* ifndef HAVE_LIBIDN2 */ - break; - case 'o': - FULLCHECK("idnout"); -#ifndef HAVE_LIBIDN2 - if (state) { - fprintf(stderr, - ";; IDN output support" - " not enabled\n"); - } -#else /* ifndef HAVE_LIBIDN2 */ lookup->idnout = state; -#endif /* ifndef HAVE_LIBIDN2 */ + break; + case 'i': /* (compat) */ + FULLCHECK("idnin"); + lookup->idnin = state; + break; + case 'o': /* (compat) */ + FULLCHECK("idnout"); + lookup->idnout = state; break; default: goto invalid_option; } +#ifndef HAVE_LIBIDN2 + if (state) { + printf(";; IDN support " + "is not available\n"); + } +#endif /* ifndef HAVE_LIBIDN2 */ break; default: goto invalid_option; diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst index a5bfb86556..409dee4b28 100644 --- a/bin/dig/dig.rst +++ b/bin/dig/dig.rst @@ -432,28 +432,19 @@ abbreviation is unambiguous; for example, :option:`+cd` is equivalent to form answers are requested, the default is not to show the source address and port number of the server that provided the answer. -.. option:: +idnin, +noidnin +.. option:: +idn, +noidn - This option processes [or does not process] IDN domain names on input. This requires - ``IDN SUPPORT`` to have been enabled at compile time. + Enable or disable IDN processing. By default IDN is enabled for + input query names, and for display when the output is a terminal. - The default is to process IDN input when standard output is a tty. - The IDN processing on input is disabled when :program:`dig` output is redirected - to files, pipes, and other non-tty file descriptors. - -.. option:: +idnout, +noidnout - - This option converts [or does not convert] puny code on output. This requires - ``IDN SUPPORT`` to have been enabled at compile time. - - The default is to process puny code on output when standard output is - a tty. The puny code processing on output is disabled when :program:`dig` output - is redirected to files, pipes, and other non-tty file descriptors. + You can also turn off :program:`dig`'s IDN processing by setting + the ``IDN_DISABLE`` environment variable. .. option:: +ignore, +noignore - This option ignores [or does not ignore] truncation in UDP responses instead of retrying with TCP. By - default, TCP retries are performed. + This option ignores [or does not ignore] truncation in UDP + responses instead of retrying with TCP. By default, TCP retries are + performed. .. option:: +keepalive, +nokeepalive @@ -750,17 +741,6 @@ each lookup. The final query has a local query option of :option:`+qr` which means that :program:`dig` does not print the initial query when it looks up the NS records for ``isc.org``. -IDN Support -~~~~~~~~~~~ - -If :program:`dig` has been built with IDN (internationalized domain name) -support, it can accept and display non-ASCII domain names. :program:`dig` -appropriately converts character encoding of a domain name before sending -a request to a DNS server or displaying a reply from the server. -To turn off IDN support, use the parameters -:option:`+idnin` and :option:`+idnout`, or define the ``IDN_DISABLE`` environment -variable. - Return Codes ~~~~~~~~~~~~ diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index c9a43c8eb9..b7657cdd0c 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -116,11 +116,7 @@ static char servercookie[256]; #ifdef HAVE_LIBIDN2 static void -idn_locale_to_ace(const char *src, char *dst, size_t dstlen); -static void -idn_ace_to_locale(const char *src, char **dst); -static isc_result_t -idn_output_filter(isc_buffer_t *buffer, unsigned int used_org); +idn_input(const char *src, char *dst, size_t dstlen); #endif /* HAVE_LIBIDN2 */ isc_nmhandle_t *keep = NULL; @@ -585,8 +581,13 @@ clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) { dig_lookup_t * make_empty_lookup(void) { dig_lookup_t *looknew; + int idnin = false, idnout = false; + #ifdef HAVE_LIBIDN2 - bool idn_allowed = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false; + if (getenv("IDN_DISABLE") == NULL) { + idnin = true; + idnout = isatty(1); + } #endif /* HAVE_LIBIDN2 */ debug("make_empty_lookup()"); @@ -603,10 +604,8 @@ make_empty_lookup(void) { .besteffort = true, .opcode = dns_opcode_query, .badcookie = true, -#ifdef HAVE_LIBIDN2 - .idnin = idn_allowed, - .idnout = idn_allowed, -#endif /* HAVE_LIBIDN2 */ + .idnin = idnin, + .idnout = idnout, .udpsize = -1, .edns = -1, .recurse = true, @@ -2220,7 +2219,7 @@ setup_lookup(dig_lookup_t *lookup) { textname = lookup->textname; #ifdef HAVE_LIBIDN2 if (lookup->idnin) { - idn_locale_to_ace(textname, idn_textname, sizeof(idn_textname)); + idn_input(textname, idn_textname, sizeof(idn_textname)); debug("idn_textname: %s", idn_textname); textname = idn_textname; } @@ -2251,8 +2250,7 @@ setup_lookup(dig_lookup_t *lookup) { origin = lookup->origin->origin; #ifdef HAVE_LIBIDN2 if (lookup->idnin) { - idn_locale_to_ace(origin, idn_origin, - sizeof(idn_origin)); + idn_input(origin, idn_origin, sizeof(idn_origin)); debug("trying idn origin %s", idn_origin); origin = idn_origin; } @@ -4680,57 +4678,48 @@ destroy_libs(void) { } #ifdef HAVE_LIBIDN2 + static isc_result_t -idn_output_filter(isc_buffer_t *buffer, unsigned int used_org) { - char src[MXNAME], *dst = NULL; +idn_filter(isc_buffer_t *buffer, unsigned start) { + char src[MXNAME]; + char *dst = NULL; size_t srclen, dstlen; - isc_result_t result = ISC_R_SUCCESS; + int res; /* * Copy name from 'buffer' to 'src' and terminate it with NULL. */ - srclen = isc_buffer_usedlength(buffer) - used_org; - if (srclen >= sizeof(src)) { - warn("Input name too long to perform IDN conversion"); - goto cleanup; - } - memmove(src, (char *)isc_buffer_base(buffer) + used_org, srclen); + srclen = isc_buffer_usedlength(buffer) - start; + INSIST(srclen < sizeof(src)); + memmove(src, (char *)isc_buffer_base(buffer) + start, srclen); src[srclen] = '\0'; + /* + * Try to convert the name; leave it unchanged if conversion fails. + */ systemlocale(LC_ALL); - - /* - * Convert 'src' to the current locale's character encoding. - */ - idn_ace_to_locale(src, &dst); - + res = idn2_to_unicode_8zlz(src, &dst, IDN2_NONTRANSITIONAL); + if (res == IDN2_DISALLOWED) { + res = idn2_to_unicode_8zlz(src, &dst, IDN2_TRANSITIONAL); + } resetlocale(LC_ALL); - - /* - * Check whether the converted name will fit back into 'buffer'. - */ - dstlen = strlen(dst); - if (isc_buffer_length(buffer) < used_org + dstlen) { - result = ISC_R_NOSPACE; - goto cleanup; + if (res != IDN2_OK) { + return (ISC_R_SUCCESS); } /* - * Put the converted name back into 'buffer'. + * Copy the converted back into 'buffer' if it fits. */ + dstlen = strlen(dst); + if (isc_buffer_length(buffer) < start + dstlen) { + return (ISC_R_NOSPACE); + } isc_buffer_subtract(buffer, srclen); memmove(isc_buffer_used(buffer), dst, dstlen); isc_buffer_add(buffer, dstlen); - /* - * Clean up. - */ -cleanup: - if (dst != NULL) { - idn2_free(dst); - } - - return (result); + idn2_free(dst); + return (ISC_R_SUCCESS); } /*% @@ -4741,126 +4730,42 @@ cleanup: * 'dst' MUST be large enough to hold any valid domain name. */ static void -idn_locale_to_ace(const char *src, char *dst, size_t dstlen) { - const char *final_src; - char *ascii_src; +idn_input(const char *src, char *dst, size_t dstlen) { + char *ascii = NULL; + size_t len; int res; - systemlocale(LC_ALL); - /* * We trust libidn2 to return an error if 'src' is too large to be a * valid domain name. + * + * If conversion fails under IDNA2008 rules, retry with transitional + * rules. The aim is that characters whose interpretation changed will + * be handled under the new rules, but we will accept characters (such + * as emoji) that were OK but are now forbidden. */ - res = idn2_to_ascii_lz(src, &ascii_src, IDN2_NONTRANSITIONAL); - if (res == IDN2_DISALLOWED) { - res = idn2_to_ascii_lz(src, &ascii_src, IDN2_TRANSITIONAL); - } - if (res != IDN2_OK) { - fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnin", - src, idn2_strerror(res)); - } - - /* - * idn2_to_ascii_lz() normalizes all strings to lower case, but we - * generally don't want to lowercase all input strings; make sure to - * return the original case if the two strings differ only in case. - */ - final_src = (strcasecmp(src, ascii_src) == 0 ? src : ascii_src); - - (void)strlcpy(dst, final_src, dstlen); - - idn2_free(ascii_src); - - resetlocale(LC_ALL); -} - -/*% - * Convert 'src', which is an ACE string suitable for use in the DNS, into a - * string using the current locale's character encoding, storing the conversion - * result in 'dst'. - * - * The caller MUST subsequently release 'dst' using idn2_free(). - */ -static void -idn_ace_to_locale(const char *src, char **dst) { - char *local_src, *utf8_src; - int res; - systemlocale(LC_ALL); - - /* - * We need to: - * - * 1) check whether 'src' is a valid IDNA2008 name, - * 2) if it is, output it in the current locale's character encoding. - * - * Unlike idn2_to_ascii_*(), idn2_to_unicode_*() functions are unable - * to perform IDNA2008 validity checks. Thus, we need to decode any - * Punycode in 'src', check if the resulting name is a valid IDNA2008 - * name, and only once we ensure it is, output that name in the current - * locale's character encoding. - * - * We could just use idn2_to_unicode_8zlz() + idn2_to_ascii_lz(), but - * then we would not be able to universally tell invalid names and - * character encoding errors apart (if the current locale uses ASCII - * for character encoding, the former function would fail even for a - * valid IDNA2008 name, as long as it contained any non-ASCII - * character). Thus, we need to take a longer route. - * - * First, convert 'src' to UTF-8, ignoring the current locale. - */ - res = idn2_to_unicode_8z8z(src, &utf8_src, 0); - if (res != IDN2_OK) { - fatal("Bad ACE string '%s' (%s), use +noidnout", src, - idn2_strerror(res)); - } - - /* - * Then, check whether decoded 'src' is a valid IDNA2008 name - * and if disallowed character is found, fallback to IDNA2003. - */ - res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_NONTRANSITIONAL); + res = idn2_to_ascii_lz(src, &ascii, IDN2_NONTRANSITIONAL); if (res == IDN2_DISALLOWED) { - res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_TRANSITIONAL); + res = idn2_to_ascii_lz(src, &ascii, IDN2_TRANSITIONAL); } - if (res != IDN2_OK) { - fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnout", - src, idn2_strerror(res)); - } - - /* - * Finally, try converting the decoded 'src' into the current locale's - * character encoding. - */ - res = idn2_to_unicode_8zlz(utf8_src, &local_src, 0); - if (res != IDN2_OK) { - static bool warned = false; - - res = idn2_to_ascii_8z(utf8_src, &local_src, 0); - if (res != IDN2_OK) { - fatal("Cannot represent '%s' " - "in the current locale nor ascii (%s), " - "use +noidnout or a different locale", - src, idn2_strerror(res)); - } else if (!warned) { - fprintf(stderr, - ";; Warning: cannot represent '%s' " - "in the current locale", - local_src); - warned = true; - } - } - - /* - * Free the interim conversion result. - */ - idn2_free(utf8_src); - - *dst = local_src; - resetlocale(LC_ALL); + + /* + * idn2_to_ascii_lz() normalizes all strings to lower case, but + * we generally don't want to lowercase all input strings; make + * sure to return the original case if the two strings differ + * only in case. + */ + if (res == IDN2_OK && strcasecmp(src, ascii) != 0) { + len = strlcpy(dst, ascii, dstlen); + } else { + len = strlcpy(dst, src, dstlen); + } + INSIST(len < dstlen); + idn2_free(ascii); } + #endif /* HAVE_LIBIDN2 */ void @@ -4868,7 +4773,7 @@ dig_idnsetup(dig_lookup_t *lookup, bool active) { #ifdef HAVE_LIBIDN2 isc_result_t result; result = dns_name_settotextfilter( - (active && lookup->idnout) ? idn_output_filter : NULL); + (active && lookup->idnout) ? idn_filter : NULL); check_result(result, "dns_name_settotextfilter"); #else UNUSED(lookup); diff --git a/bin/tests/system/idna/tests.sh b/bin/tests/system/idna/tests.sh index af5ad5787d..318bbbec49 100644 --- a/bin/tests/system/idna/tests.sh +++ b/bin/tests/system/idna/tests.sh @@ -22,17 +22,6 @@ export LC_ALL # This set of tests check the behavior of the IDNA options in "dig". # -# "dig" supports two IDNA-related options: -# -# +[no]idnin - Translates a domain name into punycode format before sending -# the query to the server. -# -# Should the input name be a punycode name, "dig +idnin" will also -# validate the punycode, rejecting it if it is invalid. -# -# +[no]idnout - Translates the received punycode domain names into appropriate -# unicode characters before displaying. -# # The tests run "dig" against an authoritative server configured with a minimal # root zone and nothing else. As a result, all queries will result in an # NXDOMAIN. The server will return the qname sent, which "dig" will display @@ -156,11 +145,12 @@ idna_fail() { ascii_case_preservation_test() { text="Checking valid ASCII label" - idna_test "$text" "" LocalhosT LocalhosT. + idna_test "$text" "+noidn" LocalhosT LocalhosT. idna_test "$text" "+noidnin +noidnout" LocalhosT LocalhosT. idna_test "$text" "+noidnin +idnout" LocalhosT LocalhosT. idna_test "$text" "+idnin +noidnout" LocalhosT LocalhosT. idna_test "$text" "+idnin +idnout" LocalhosT LocalhosT. + idna_test "$text" "+idn" LocalhosT LocalhosT. } # Function to perform the tests if IDNA is enabled. @@ -186,12 +176,12 @@ idna_enabled_test() { # Note that ASCII characters are converted to lower-case. text="Checking valid non-ASCII label" - idna_test "$text" "" "München" "M\195\188nchen." + idna_test "$text" "+noidn" "München" "M\195\188nchen." idna_test "$text" "+noidnin +noidnout" "München" "M\195\188nchen." idna_test "$text" "+noidnin +idnout" "München" "M\195\188nchen." idna_test "$text" "+idnin +noidnout" "München" "xn--mnchen-3ya." idna_test "$text" "+idnin +idnout" "München" "münchen." - + idna_test "$text" "+idn" "München" "münchen." # Tests of transitional processing of a valid U-label # @@ -206,28 +196,28 @@ idna_enabled_test() { # under IDNA2003, go to www.fass.example but under IDNA2008 would end up at # www.fa\195\159.example - a different web site). # - # BIND has adopted a hard transition, so this test checks that these - # transitional mapping is not used. The tests are essentially the same as - # for the valid U-label. + # BIND has adopted a (mostly) hard transition, so this test checks that + # the transitional mapping is not used for characters that are valid in + # IDNA2008. The tests are essentially the same as for the valid U-label. text="Checking that non-transitional IDNA processing is used" - idna_test "$text" "" "faß.de" "fa\195\159.de." + idna_test "$text" "+noidn" "faß.de" "fa\195\159.de." idna_test "$text" "+noidnin +noidnout" "faß.de" "fa\195\159.de." idna_test "$text" "+noidnin +idnout" "faß.de" "fa\195\159.de." idna_test "$text" "+idnin +noidnout" "faß.de" "xn--fa-hia.de." idna_test "$text" "+idnin +idnout" "faß.de" "faß.de." + idna_test "$text" "+idn" "faß.de" "faß.de." # Another problem character. The final character in the first label mapped # onto the Greek sigma character ("σ") in IDNA2003. text="Second check that non-transitional IDNA processing is used" - idna_test "$text" "" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com." + idna_test "$text" "+noidn" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com." idna_test "$text" "+noidnin +noidnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com." idna_test "$text" "+noidnin +idnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com." idna_test "$text" "+idnin +noidnout" "βόλος.com" "xn--nxasmm1c.com." idna_test "$text" "+idnin +idnout" "βόλος.com" "βόλος.com." - - + idna_test "$text" "+idn" "βόλος.com" "βόλος.com." # Tests of a valid A-label (i.e. starting xn--) # @@ -239,11 +229,12 @@ idna_enabled_test() { # The "+[no]idnin" flag has no effect in these cases. text="Checking valid A-label" - idna_test "$text" "" "xn--nxasmq6b.com" "xn--nxasmq6b.com." + idna_test "$text" "+noidn" "xn--nxasmq6b.com" "xn--nxasmq6b.com." idna_test "$text" "+noidnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com." idna_test "$text" "+noidnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com." idna_test "$text" "+idnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com." idna_test "$text" "+idnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com." + idna_test "$text" "+idn" "xn--nxasmq6b.com" "βόλοσ.com." # Test of valid A-label in locale that cannot display it # @@ -258,17 +249,16 @@ idna_enabled_test() { text="Checking valid A-label in C locale" label="xn--nxasmq6b.com" if command -v idn2 >/dev/null && ! idn2 -d "$label" >/dev/null 2>/dev/null; then - idna_test "$text" "" "$label" "$label." + idna_test "$text" "+noidn" "$label" "$label." idna_test "$text" "+noidnin +noidnout" "$label" "$label." idna_test "$text" "+noidnin +idnout" "$label" "$label." idna_test "$text" "+idnin +noidnout" "$label" "$label." idna_test "$text" "+idnin +idnout" "$label" "$label." idna_test "$text" "+noidnin +idnout" "$label" "$label." + idna_test "$text" "+idn" "$label" "$label." fi LC_ALL="${saved_LC_ALL}" - - # Tests of invalid A-labels # # +noidnin: The label is sent as-is to the server and dig will display the @@ -277,42 +267,48 @@ idna_enabled_test() { # # +[no]idnout: If the label makes it to the server (via +noidnin), "dig" # should report an error if +idnout is specified. + # + # +idn=lax: The label is sent and printed as-is. # The minimum length of a punycode A-label is 7 characters. Check that # a shorter label is detected and rejected. text="Checking punycode label shorter than minimum valid length" - idna_test "$text" "" "xn--xx" "xn--xx." + idna_test "$text" "+noidn" "xn--xx" "xn--xx." idna_test "$text" "+noidnin +noidnout" "xn--xx" "xn--xx." - idna_fail "$text" "+noidnin +idnout" "xn--xx" - idna_fail "$text" "+idnin +noidnout" "xn--xx" - idna_fail "$text" "+idnin +idnout" "xn--xx" + idna_test "$text" "+noidnin +idnout" "xn--xx" "xn--xx." + idna_test "$text" "+idnin +noidnout" "xn--xx" "xn--xx." + idna_test "$text" "+idnin +idnout" "xn--xx" "xn--xx." + idna_test "$text" "+idn" "xn--xx" "xn--xx." # Fake A-label - the string does not translate to anything. + # This name is a syntax error: IDNA expects be punycode-encoded + # non-ascii characters after the last hyphen, but they are missing + # in this test. text="Checking fake A-label" - idna_test "$text" "" "xn--ahahah" "xn--ahahah." - idna_test "$text" "+noidnin +noidnout" "xn--ahahah" "xn--ahahah." - idna_fail "$text" "+noidnin +idnout" "xn--ahahah" - idna_fail "$text" "+idnin +noidnout" "xn--ahahah" - idna_fail "$text" "+idnin +idnout" "xn--ahahah" + idna_test "$text" "+noidn" "xn--ah-" "xn--ah-." + idna_test "$text" "+noidnin +noidnout" "xn--ah-" "xn--ah-." + idna_test "$text" "+noidnin +idnout" "xn--ah-" "xn--ah-." + idna_test "$text" "+idnin +noidnout" "xn--ah-" "xn--ah-." + idna_test "$text" "+idnin +idnout" "xn--ah-" "xn--ah-." + idna_test "$text" "+idn" "xn--ah-" "xn--ah-." # Too long a label. The punycode string is too long (at 64 characters). # BIND rejects such labels: with +idnin label="xn--xflod18hstflod18hstflod18hstflod18hstflod18hstflod18-1iejjjj" text="Checking punycode label longer than maximum valid length" - idna_fail "$text" "" "$label" + idna_fail "$text" "+noidn" "$label" idna_fail "$text" "+noidnin +noidnout" "$label" idna_fail "$text" "+noidnin +idnout" "$label" idna_fail "$text" "+idnin +noidnout" "$label" idna_fail "$text" "+idnin +idnout" "$label" + idna_fail "$text" "+idn" "$label" # Tests of a valid unicode string but an invalid U-label (input) # - # Symbols are not valid IDNA2008 names. Check whether dig rejects them - # when they are supplied on the command line to ensure no IDNA2003 - # fallbacks are in place. + # Symbols are not valid IDNA2008 names, but are allowed by IDNA2003. # # +noidnin: "dig" should send unicode octets to the server and display the # returned qname in the same form. @@ -321,22 +317,16 @@ idna_enabled_test() { # The +[no]idnout options should not have any effect on the test. text="Checking invalid input U-label" - idna_test "$text" "" "√.com" "\226\136\154.com." + idna_test "$text" "+noidn" "√.com" "\226\136\154.com." idna_test "$text" "+noidnin +noidnout" "√.com" "\226\136\154.com." idna_test "$text" "+noidnin +idnout" "√.com" "\226\136\154.com." idna_test "$text" "+idnin +noidnout" "√.com" "xn--19g.com." idna_test "$text" "+idnin +idnout" "√.com" "√.com." + idna_test "$text" "+idn" "√.com" "√.com." # Tests of a valid unicode string but an invalid U-label (output) # - # Symbols are not valid IDNA2008 names. Check whether dig rejects them - # when they are received in DNS responses to ensure no IDNA2003 fallbacks - # are in place. - # - # Note that "+idnin +noidnout" is not tested because libidn2 2.2.0+ parses - # Punycode more strictly than older versions and thus dig fails with that - # combination of options with libidn2 2.2.0+ but succeeds with older - # versions. + # Symbols are not valid IDNA2008 names, but are allowed by IDNA2003. # # +noidnout: "dig" should send the ACE string to the server and display the # returned qname. @@ -345,28 +335,32 @@ idna_enabled_test() { # The +[no]idnin options should not have any effect on the test. text="Checking invalid output U-label" - idna_test "$text" "" "xn--19g" "xn--19g." + idna_test "$text" "+noidn" "xn--19g" "xn--19g." idna_test "$text" "+noidnin +noidnout" "xn--19g" "xn--19g." idna_test "$text" "+noidnin +idnout" "xn--19g" "√." + idna_test "$text" "+idnin +noidnout" "xn--19g" "xn--19g." idna_test "$text" "+idnin +idnout" "xn--19g" "√." - + idna_test "$text" "+idn" "xn--19g" "√." # Test that non-letter characters are preserved in the output. When # UseSTD3ASCIIRules are enabled, it would mangle non-letter characters like # `_` (underscore) and `*` (wildcard. text="Checking valid non-letter characters" - idna_test "$text" "" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com." + idna_test "$text" "+noidn" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com." idna_test "$text" "+noidnin +noidnout" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com." idna_test "$text" "+noidnin +idnout" "*.xn--nxasmq6b.com" "*.βόλοσ.com." idna_test "$text" "+idnin +noidnout" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com." idna_test "$text" "+idnin +idnout" "*.xn--nxasmq6b.com" "*.βόλοσ.com." + idna_test "$text" "+idn" "*.xn--nxasmq6b.com" "*.βόλοσ.com." - idna_test "$text" "" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com." + idna_test "$text" "+noidn" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com." idna_test "$text" "+noidnin +noidnout" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com." idna_test "$text" "+noidnin +idnout" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." idna_test "$text" "+idnin +noidnout" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com." idna_test "$text" "+idnin +idnout" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." + idna_test "$text" "+idn=strict" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." + idna_test "$text" "+idn=lax" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." } diff --git a/doc/man/dig.1in b/doc/man/dig.1in index d5f42ed852..171d7fc602 100644 --- a/doc/man/dig.1in +++ b/doc/man/dig.1in @@ -502,29 +502,19 @@ address and port number of the server that provided the answer. .UNINDENT .INDENT 0.0 .TP -.B +idnin, +noidnin -This option processes [or does not process] IDN domain names on input. This requires -\fBIDN SUPPORT\fP to have been enabled at compile time. +.B +idn, +noidn +Enable or disable IDN processing. By default IDN is enabled for +input query names, and for display when the output is a terminal. .sp -The default is to process IDN input when standard output is a tty. -The IDN processing on input is disabled when \fBdig\fP output is redirected -to files, pipes, and other non\-tty file descriptors. -.UNINDENT -.INDENT 0.0 -.TP -.B +idnout, +noidnout -This option converts [or does not convert] puny code on output. This requires -\fBIDN SUPPORT\fP to have been enabled at compile time. -.sp -The default is to process puny code on output when standard output is -a tty. The puny code processing on output is disabled when \fBdig\fP output -is redirected to files, pipes, and other non\-tty file descriptors. +You can also turn off \fBdig\fP\(aqs IDN processing by setting +the \fBIDN_DISABLE\fP environment variable. .UNINDENT .INDENT 0.0 .TP .B +ignore, +noignore -This option ignores [or does not ignore] truncation in UDP responses instead of retrying with TCP. By -default, TCP retries are performed. +This option ignores [or does not ignore] truncation in UDP +responses instead of retrying with TCP. By default, TCP retries are +performed. .UNINDENT .INDENT 0.0 .TP @@ -867,15 +857,6 @@ and a query for the NS records of \fBisc.org\fP\&. A global query option of each lookup. The final query has a local query option of \fI\%+qr\fP which means that \fBdig\fP does not print the initial query when it looks up the NS records for \fBisc.org\fP\&. -.SH IDN SUPPORT -.sp -If \fBdig\fP has been built with IDN (internationalized domain name) -support, it can accept and display non\-ASCII domain names. \fBdig\fP -appropriately converts character encoding of a domain name before sending -a request to a DNS server or displaying a reply from the server. -To turn off IDN support, use the parameters -\fI\%+idnin\fP and \fI\%+idnout\fP, or define the \fBIDN_DISABLE\fP environment -variable. .SH RETURN CODES .sp \fBdig\fP return codes are: