Allow wildcard CNAME records in authoritative zones.

This commit is contained in:
Simon Kelley
2016-12-13 16:44:11 +00:00
parent c6af3a32f2
commit b637d7815d
5 changed files with 74 additions and 26 deletions

View File

@@ -116,7 +116,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
struct interface_name *intr;
struct naptr *na;
struct all_addr addr;
struct cname *a;
struct cname *a, *candidate;
unsigned int wclen;
/* Clear buffer beyond request to avoid risk of
information disclosure. */
@@ -137,6 +138,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
unsigned short flag = 0;
int found = 0;
int cname_wildcard = 0;
/* save pointer to name for copying into answers */
nameoffset = p - (unsigned char *)header;
@@ -411,25 +413,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
}
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(name, a->alias) )
{
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
strcpy(name, a->target);
if (!strchr(name, '.'))
{
strcat(name, ".");
strcat(name, zone->domain);
}
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, &nameoffset,
T_CNAME, C_IN, "d", name))
anscount++;
goto cname_restart;
}
if (!cut)
{
nxdomain = 0;
@@ -536,7 +519,60 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
if (!found)
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
{
/* Check for possible wildcard match against *.domain
return length of match, to get longest.
Note that if return length of wildcard section, so
we match b.simon to _both_ *.simon and b.simon
but return a longer (better) match to b.simon.
*/
for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
if (a->alias[0] == '*')
{
char *test = name;
while ((test = strchr(test+1, '.')))
{
if (hostname_isequal(test, &(a->alias[1])))
{
if (strlen(test) > wclen && !cname_wildcard)
{
wclen = strlen(test);
candidate = a;
cname_wildcard = 1;
}
break;
}
}
}
else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
{
/* Simple case, no wildcard */
wclen = strlen(a->alias);
candidate = a;
}
if (candidate)
{
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
strcpy(name, candidate->target);
if (!strchr(name, '.'))
{
strcat(name, ".");
strcat(name, zone->domain);
}
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, &nameoffset,
T_CNAME, C_IN, "d", name))
anscount++;
goto cname_restart;
}
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
}
}

View File

@@ -774,7 +774,8 @@ static void add_hosts_cname(struct crec *target)
struct cname *a;
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(cache_get_name(target), a->target) &&
if (a->alias[1] != '*' &&
hostname_isequal(cache_get_name(target), a->target) &&
(crec = whine_malloc(sizeof(struct crec))))
{
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
@@ -1056,7 +1057,8 @@ void cache_reload(void)
/* Add CNAMEs to interface_names to the cache */
for (a = daemon->cnames; a; a = a->next)
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(a->target, intr->name) &&
if (a->alias[1] != '*' &&
hostname_isequal(a->target, intr->name) &&
((cache = whine_malloc(sizeof(struct crec)))))
{
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
@@ -1177,7 +1179,8 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
struct cname *a;
for (a = daemon->cnames; a; a = a->next)
if (hostname_isequal(cache_get_name(target), a->target))
if (a->alias[1] != '*' &&
hostname_isequal(cache_get_name(target), a->target))
{
if ((aliasc = dhcp_spare))
dhcp_spare = dhcp_spare->next;

View File

@@ -323,7 +323,7 @@ int hostname_isequal(const char *a, const char *b)
return 1;
}
time_t dnsmasq_time(void)
{
#ifdef HAVE_BROKEN_RTC