summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2014-02-06 14:45:17 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2014-02-06 14:45:17 +0000
commit610e782a29958aa2e3d6f0955cb01dab2016e4f6 (patch)
treed33b232575a96902c46d31f514abea433af1e586
parent854cf269072900447e13f768a3c9d1af59a303f4 (diff)
downloaddnsmasq-610e782a29958aa2e3d6f0955cb01dab2016e4f6.tar.gz
Fix stack-smashing crash in DNSSEC. Thanks to Henk Jan Agteresch.
-rw-r--r--src/cache.c45
-rw-r--r--src/dnsmasq.h2
-rw-r--r--src/dnssec.c4
-rw-r--r--src/forward.c9
-rw-r--r--src/rfc1035.c6
5 files changed, 44 insertions, 22 deletions
diff --git a/src/cache.c b/src/cache.c
index 19a5d61..66b52d2 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -55,7 +55,9 @@ static const struct {
{ 41, "OPT" },
{ 43, "DS" },
{ 46, "RRSIG" },
+ { 47, "NSEC" },
{ 48, "DNSKEY" },
+ { 50, "NSEC3" },
{ 249, "TKEY" },
{ 250, "TSIG" },
{ 251, "IXFR" },
@@ -1301,12 +1303,10 @@ void dump_cache(time_t now)
{
if (cache->flags & F_DNSKEY)
{
- char tp[20];
/* RRSIG */
- querystr("", tp, cache->addr.sig.type_covered);
a = daemon->addrbuff;
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
{
@@ -1382,14 +1382,45 @@ char *record_source(int index)
return "<unknown>";
}
-void querystr(char *desc, char *str, unsigned short type)
+char *querystr(char *desc, unsigned short type)
{
unsigned int i;
-
- sprintf(str, "%s[type=%d]", desc, type);
+ int len = 10; /* strlen("type=xxxxx") */
+ const char *types = NULL;
+ static char *buff = NULL;
+ static int bufflen = 0;
+
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
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)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 58a4fe2..a84ac36 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -991,7 +991,7 @@ extern struct daemon {
void cache_init(void);
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
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 all_addr *addr, time_t now,
unsigned int prot);
diff --git a/src/dnssec.c b/src/dnssec.c
index 7a69528..8263b3e 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -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)
{
unsigned char *p;
- char types[20];
-
- querystr("dnssec-query", types, type);
+ char *types = querystr("dnssec-query", type);
if (addr->sa.sa_family == AF_INET)
log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
diff --git a/src/forward.c b/src/forward.c
index ed853a3..073b2c9 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -1117,13 +1117,11 @@ void receive_query(struct listener *listen, time_t now)
if (extract_request(header, (size_t)n, daemon->namebuff, &type))
{
- char types[20];
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
-
- querystr(auth_dns ? "auth" : "query", types, type);
-
+ char *types = querystr(auth_dns ? "auth" : "query", type);
+
if (listen->family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
(struct all_addr *)&source_addr.in.sin_addr, types);
@@ -1290,11 +1288,10 @@ unsigned char *tcp_request(int confd, time_t now,
if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
{
- char types[20];
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
- querystr(auth_dns ? "auth" : "query", types, qtype);
+ char *types = querystr(auth_dns ? "auth" : "query", qtype);
if (peer_addr.sa.sa_family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 26cda15..ac8c4ae 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -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)))
{
if (qtype == T_RRSIG)
- {
- char types[20];
- querystr("rrsig", types, crecp->addr.sig.type_covered);
- log_query(F_RRNAME, name, NULL, types);
- }
+ log_query(F_RRNAME, name, NULL, querystr("rrsig", crecp->addr.sig.type_covered));
if ((keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)) &&
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
crec_ttl(crecp, now), &nameoffset,