Commit 610e782a authored by Simon Kelley's avatar Simon Kelley

Fix stack-smashing crash in DNSSEC. Thanks to Henk Jan Agteresch.

parent 854cf269
...@@ -55,7 +55,9 @@ static const struct { ...@@ -55,7 +55,9 @@ static const struct {
{ 41, "OPT" }, { 41, "OPT" },
{ 43, "DS" }, { 43, "DS" },
{ 46, "RRSIG" }, { 46, "RRSIG" },
{ 47, "NSEC" },
{ 48, "DNSKEY" }, { 48, "DNSKEY" },
{ 50, "NSEC3" },
{ 249, "TKEY" }, { 249, "TKEY" },
{ 250, "TSIG" }, { 250, "TSIG" },
{ 251, "IXFR" }, { 251, "IXFR" },
...@@ -1301,12 +1303,10 @@ void dump_cache(time_t now) ...@@ -1301,12 +1303,10 @@ void dump_cache(time_t now)
{ {
if (cache->flags & F_DNSKEY) if (cache->flags & F_DNSKEY)
{ {
char tp[20];
/* RRSIG */ /* RRSIG */
querystr("", tp, cache->addr.sig.type_covered);
a = daemon->addrbuff; a = daemon->addrbuff;
sprintf(a, "%5u %3u %s", cache->addr.sig.keytag, sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
cache->addr.sig.algo, tp); cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
} }
else else
{ {
...@@ -1382,14 +1382,45 @@ char *record_source(int index) ...@@ -1382,14 +1382,45 @@ char *record_source(int index)
return "<unknown>"; return "<unknown>";
} }
void querystr(char *desc, char *str, unsigned short type) char *querystr(char *desc, unsigned short type)
{ {
unsigned int i; unsigned int i;
int len = 10; /* strlen("type=xxxxx") */
sprintf(str, "%s[type=%d]", desc, type); const char *types = NULL;
static char *buff = NULL;
static int bufflen = 0;
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++) for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
if (typestr[i].type == type) if (typestr[i].type == type)
sprintf(str,"%s[%s]", desc, typestr[i].name); {
types = typestr[i].name;
len = strlen(types);
break;
}
len += 3; /* braces, terminator */
len += strlen(desc);
if (!buff || bufflen < len)
{
if (buff)
free(buff);
else if (len < 20)
len = 20;
buff = whine_malloc(len);
bufflen = len;
}
if (buff)
{
if (types)
sprintf(buff, "%s[%s]", desc, types);
else
sprintf(buff, "%s[type=%d]", desc, type);
}
return buff ? buff : "";
} }
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg) void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
......
...@@ -991,7 +991,7 @@ extern struct daemon { ...@@ -991,7 +991,7 @@ extern struct daemon {
void cache_init(void); void cache_init(void);
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg); void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
char *record_source(int index); char *record_source(int index);
void querystr(char *desc, char *str, unsigned short type); char *querystr(char *desc, unsigned short type);
struct crec *cache_find_by_addr(struct crec *crecp, struct crec *cache_find_by_addr(struct crec *crecp,
struct all_addr *addr, time_t now, struct all_addr *addr, time_t now,
unsigned int prot); unsigned int prot);
......
...@@ -1387,9 +1387,7 @@ int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen) ...@@ -1387,9 +1387,7 @@ int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr) size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
{ {
unsigned char *p; unsigned char *p;
char types[20]; char *types = querystr("dnssec-query", type);
querystr("dnssec-query", types, type);
if (addr->sa.sa_family == AF_INET) if (addr->sa.sa_family == AF_INET)
log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types); log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
......
...@@ -1117,13 +1117,11 @@ void receive_query(struct listener *listen, time_t now) ...@@ -1117,13 +1117,11 @@ void receive_query(struct listener *listen, time_t now)
if (extract_request(header, (size_t)n, daemon->namebuff, &type)) if (extract_request(header, (size_t)n, daemon->namebuff, &type))
{ {
char types[20];
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
struct auth_zone *zone; struct auth_zone *zone;
#endif #endif
char *types = querystr(auth_dns ? "auth" : "query", type);
querystr(auth_dns ? "auth" : "query", types, type);
if (listen->family == AF_INET) if (listen->family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
(struct all_addr *)&source_addr.in.sin_addr, types); (struct all_addr *)&source_addr.in.sin_addr, types);
...@@ -1290,11 +1288,10 @@ unsigned char *tcp_request(int confd, time_t now, ...@@ -1290,11 +1288,10 @@ unsigned char *tcp_request(int confd, time_t now,
if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype))) if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
{ {
char types[20];
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
struct auth_zone *zone; struct auth_zone *zone;
#endif #endif
querystr(auth_dns ? "auth" : "query", types, qtype); char *types = querystr(auth_dns ? "auth" : "query", qtype);
if (peer_addr.sa.sa_family == AF_INET) if (peer_addr.sa.sa_family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
......
...@@ -1628,11 +1628,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, ...@@ -1628,11 +1628,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
(keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL))) (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
{ {
if (qtype == T_RRSIG) if (qtype == T_RRSIG)
{ log_query(F_RRNAME, name, NULL, querystr("rrsig", crecp->addr.sig.type_covered));
char types[20];
querystr("rrsig", types, crecp->addr.sig.type_covered);
log_query(F_RRNAME, name, NULL, types);
}
if ((keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)) && if ((keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)) &&
add_resource_record(header, limit, &trunc, nameoffset, &ansp, add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), &nameoffset, crec_ttl(crecp, now), &nameoffset,
......
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