2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

Merge branch '3527-dig-idna-relaxed' into 'main'

More lenient IDNA processing in dig

Closes #3527

See merge request isc-projects/bind9!6738
This commit is contained in:
Tony Finch
2022-09-12 11:09:38 +00:00
7 changed files with 149 additions and 289 deletions

View File

@@ -1,3 +1,7 @@
5964. [func] When an international domain name is not valid, DiG will
now pass it through unchanged, instead of stopping with
an error message. [GL #3527]
5963. [bug] Ensure struct named_server is properly initialized.
[GL #6531]

View File

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

View File

@@ -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
~~~~~~~~~~~~

View File

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

View File

@@ -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."
}

View File

@@ -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:

View File

@@ -35,7 +35,10 @@ Removed Features
Feature Changes
~~~~~~~~~~~~~~~
- None.
- When an international domain name is not valid according to IDNA2008,
:program:`dig` will now try to convert it according to IDNA2003 rules,
or pass it through unchanged, instead of stopping with an error message.
You can use the ``idna2`` utility for checking IDNA syntax. :gl:`#3485`.
Bug Fixes
~~~~~~~~~