mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-28 13:08:06 +00:00
More lenient IDNA processing in dig
If there are any problems with IDN processing, DiG will now quietly handle the name as if IDN were disabled. This means that international query names are rendered verbatim on the wire, and ACE names are printed raw without conversion to UTF8. If you want to check the syntax of international domain names, use the `idn2` utility.
This commit is contained in:
parent
8b9dba53dd
commit
f820ef49bf
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user