Commit 69a815aa authored by Simon Kelley's avatar Simon Kelley

Fix loss of undercores in domain names when using libidn2.

libidn2 strips underscores from international domain names
when encoding them. Indeed, it strips underscores even if
no encoding is necessary, which breaks SRV records.

Don't submit domain names to IDN encoding if they contain
one or more underscores to fix this.
parent 1d224949
......@@ -111,6 +111,7 @@ u64 rand64(void)
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
}
/* returns 2 if names is OK but contains one or more underscores */
static int check_name(char *in)
{
/* remove trailing .
......@@ -118,6 +119,7 @@ static int check_name(char *in)
size_t dotgap = 0, l = strlen(in);
char c;
int nowhite = 0;
int hasuscore = 0;
if (l == 0 || l > MAXDNAME) return 0;
......@@ -141,13 +143,17 @@ static int check_name(char *in)
return 0;
#endif
else if (c != ' ')
nowhite = 1;
{
nowhite = 1;
if (c == '_')
hasuscore = 1;
}
}
if (!nowhite)
return 0;
return 1;
return hasuscore ? 2 : 1;
}
/* Hostnames have a more limited valid charset than domain names
......@@ -186,43 +192,48 @@ int legal_hostname(char *name)
char *canonicalise(char *in, int *nomem)
{
char *ret = NULL;
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
int rc;
#endif
if (nomem)
*nomem = 0;
if (!check_name(in))
if (!(rc = check_name(in)))
return NULL;
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
/* libidn2 strips underscores, so don't do IDN processing
if the name has an underscore (check_name() returned 2) */
if (rc != 2)
{
#ifdef HAVE_LIBIDN2
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
if (rc == IDN2_DISALLOWED)
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
if (rc == IDN2_DISALLOWED)
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
#else
rc = idna_to_ascii_lz(in, &ret, 0);
rc = idna_to_ascii_lz(in, &ret, 0);
#endif
if (rc != IDNA_SUCCESS)
{
if (ret)
free(ret);
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
if (rc != IDNA_SUCCESS)
{
my_syslog(LOG_ERR, _("failed to allocate memory"));
*nomem = 1;
if (ret)
free(ret);
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
{
my_syslog(LOG_ERR, _("failed to allocate memory"));
*nomem = 1;
}
return NULL;
}
return NULL;
return ret;
}
#else
#endif
if ((ret = whine_malloc(strlen(in)+1)))
strcpy(ret, in);
else if (nomem)
*nomem = 1;
#endif
return ret;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment