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:
4
CHANGES
4
CHANGES
@@ -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]
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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."
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
~~~~~~~~~
|
||||
|
Reference in New Issue
Block a user