Add some checks to make sure we're not running past the end of the RR

we're dissecting.  (Some RR's still don't do that check, as they don't
maintain an "rr_len" variable, and as "get_dns_name()" doesn't do any
length checking.)

That obviates the need for having "compute_key_id()" check the length,
as we won't even get to calling it if the RR is too short.  Have it
still do a check for sanity, but just abort if the check fails, and have
it return -1 if the algorithm is unsupported.

Don't bother processing T_CERT RRs if we're not building a protocol
tree, don't fetch data from a T_CERT RR until we put it into the tree,
and fix the bug that change found, namely that we were using the wrong
variable in the "val_to_str()" call for the certificate type.

svn path=/trunk/; revision=9250
This commit is contained in:
Guy Harris 2003-12-12 23:23:57 +00:00
parent 9612f15d1a
commit c91bf1cb22
1 changed files with 144 additions and 41 deletions

View File

@ -1,7 +1,7 @@
/* packet-dns.c /* packet-dns.c
* Routines for DNS packet disassembly * Routines for DNS packet disassembly
* *
* $Id: packet-dns.c,v 1.109 2003/12/11 18:38:57 guy Exp $ * $Id: packet-dns.c,v 1.110 2003/12/12 23:23:57 guy Exp $
* *
* Ethereal - Network traffic analyzer * Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com> * By Gerald Combs <gerald@ethereal.com>
@ -890,8 +890,7 @@ static const value_string cert_vals[] = {
/** /**
* Compute the key id of a KEY RR depending of the algorithm used. * Compute the key id of a KEY RR depending of the algorithm used.
* If the specified size is bad, return -1. * If we don't support the algorithm, return -1.
* If we don't support the algorithm, return -2.
*/ */
static int static int
compute_key_id(tvbuff_t *tvb, int offset, int size, guint8 algo) compute_key_id(tvbuff_t *tvb, int offset, int size, guint8 algo)
@ -899,9 +898,7 @@ compute_key_id(tvbuff_t *tvb, int offset, int size, guint8 algo)
guint32 ac; guint32 ac;
unsigned char c1, c2; unsigned char c1, c2;
if( size < 4 ) { g_assert(size >= 4);
return -1;
}
switch( algo ) { switch( algo ) {
case DNS_ALGO_RSAMD5: case DNS_ALGO_RSAMD5:
@ -919,7 +916,7 @@ compute_key_id(tvbuff_t *tvb, int offset, int size, guint8 algo)
ac += (ac >> 16) & 0xffff; ac += (ac >> 16) & 0xffff;
return (ac & 0xffff); return (ac & 0xffff);
default: default:
return -2; return -1;
} }
} }
@ -1118,6 +1115,11 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
if (bitnames == NULL) if (bitnames == NULL)
bitnames = g_string_sized_new(128); bitnames = g_string_sized_new(128);
if (rr_len < 4) {
if (dns_tree != NULL)
goto bad_rr;
break;
}
wks_addr = tvb_get_ptr(tvb, cur_offset, 4); wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
if (cinfo != NULL) if (cinfo != NULL)
col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr)); col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
@ -1128,6 +1130,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 1)
goto bad_rr;
protocol = tvb_get_guint8(tvb, cur_offset); protocol = tvb_get_guint8(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
ipprotostr(protocol)); ipprotostr(protocol));
@ -1251,6 +1255,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
int signer_name_len; int signer_name_len;
if (dns_tree != NULL) { if (dns_tree != NULL) {
if (rr_len < 2)
goto bad_rr;
type_covered = tvb_get_ntohs(tvb, cur_offset); type_covered = tvb_get_ntohs(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)", proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
dns_type_name(type_covered), dns_type_name(type_covered),
@ -1258,22 +1264,30 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
if (rr_len < 1)
goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals, val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
"Unknown (0x%02X)")); "Unknown (0x%02X)"));
cur_offset += 1; cur_offset += 1;
rr_len -= 1; rr_len -= 1;
if (rr_len < 1)
goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u", proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
tvb_get_guint8(tvb, cur_offset)); tvb_get_guint8(tvb, cur_offset));
cur_offset += 1; cur_offset += 1;
rr_len -= 1; rr_len -= 1;
if (rr_len < 4)
goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
time_secs_to_str(tvb_get_ntohl(tvb, cur_offset))); time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
nstime.secs = tvb_get_ntohl(tvb, cur_offset); nstime.secs = tvb_get_ntohl(tvb, cur_offset);
nstime.nsecs = 0; nstime.nsecs = 0;
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
@ -1281,6 +1295,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
nstime.secs = tvb_get_ntohl(tvb, cur_offset); nstime.secs = tvb_get_ntohl(tvb, cur_offset);
nstime.nsecs = 0; nstime.nsecs = 0;
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
@ -1288,6 +1304,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 2)
goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Id of signing key(footprint): %u", proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Id of signing key(footprint): %u",
tvb_get_ntohs(tvb, cur_offset)); tvb_get_ntohs(tvb, cur_offset));
cur_offset += 2; cur_offset += 2;
@ -1299,7 +1317,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += signer_name_len; cur_offset += signer_name_len;
rr_len -= signer_name_len; rr_len -= signer_name_len;
proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature"); if (rr_len != 0)
proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
} }
} }
break; break;
@ -1314,6 +1333,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
int key_id; int key_id;
if (dns_tree != NULL) { if (dns_tree != NULL) {
if (rr_len < 2)
goto bad_rr;
flags = tvb_get_ntohs(tvb, cur_offset); flags = tvb_get_ntohs(tvb, cur_offset);
tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags); tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
flags_tree = proto_item_add_subtree(tf, ett_t_key_flags); flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
@ -1358,11 +1379,15 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
if (rr_len < 1)
goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u", proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
tvb_get_guint8(tvb, cur_offset)); tvb_get_guint8(tvb, cur_offset));
cur_offset += 1; cur_offset += 1;
rr_len -= 1; rr_len -= 1;
if (rr_len < 1)
goto bad_rr;
algo = tvb_get_guint8(tvb, cur_offset); algo = tvb_get_guint8(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
val_to_str(algo, algo_vals, "Unknown (0x%02X)")); val_to_str(algo, algo_vals, "Unknown (0x%02X)"));
@ -1370,14 +1395,13 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
rr_len -= 1; rr_len -= 1;
key_id = compute_key_id(tvb, cur_offset-4, rr_len+4, algo); key_id = compute_key_id(tvb, cur_offset-4, rr_len+4, algo);
/* XXX - -1 "can't happen", as rr_len should be >= 0; however, if (key_id == -1)
none of the RR dissectors check rr_len as we process the proto_tree_add_text(rr_tree, tvb, 0, 0, "Key id: Unknown (algorithm 0x%02X not supported)", algo);
RR. */
if (key_id == -2)
proto_tree_add_text(rr_tree, tvb, cur_offset-4, rr_len+4, "Key id: Unknown (algorithm 0x%02X not supported)", algo);
else else
proto_tree_add_text(rr_tree, tvb, cur_offset-4, rr_len+4, "Key id: %d", key_id); proto_tree_add_text(rr_tree, tvb, 0, 0, "Key id: %d", key_id);
proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
if (rr_len != 0)
proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
} }
} }
break; break;
@ -1586,28 +1610,36 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
guint8 cert_keyalg; guint8 cert_keyalg;
int rr_len = data_len; int rr_len = data_len;
cert_type = tvb_get_ntohs(tvb, cur_offset);
cur_offset += 2;
rr_len -= 2;
cert_keytag = tvb_get_ntohs(tvb, cur_offset);
cur_offset += 2;
rr_len -= 2;
cert_keyalg = tvb_get_guint8(tvb, cur_offset);
cur_offset += 1;
rr_len -= 1;
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s", if (rr_len < 2)
val_to_str(cert_keyalg, cert_vals, goto bad_rr;
cert_type = tvb_get_ntohs(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type: %s",
val_to_str(cert_type, cert_vals,
"Unknown (0x%02X)")); "Unknown (0x%02X)"));
cur_offset += 2;
rr_len -= 2;
if (rr_len < 2)
goto bad_rr;
cert_keytag = tvb_get_ntohs(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x", proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
cert_keytag); cert_keytag);
cur_offset += 2;
rr_len -= 2;
if (rr_len < 1)
goto bad_rr;
cert_keyalg = tvb_get_guint8(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
val_to_str(cert_keyalg, algo_vals, val_to_str(cert_keyalg, algo_vals,
"Unknown (0x%02X)")); "Unknown (0x%02X)"));
proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key"); cur_offset += 1;
} rr_len -= 1;
if (rr_len != 0)
proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
}
} }
break; break;
@ -1629,27 +1661,38 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
}; };
if (dns_tree != NULL) { if (dns_tree != NULL) {
if (rr_len < 2)
goto bad_rr;
keytag = tvb_get_ntohs(tvb, cur_offset); keytag = tvb_get_ntohs(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key id: %04u", keytag); proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key id: %04u", keytag);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
if (rr_len < 1)
goto bad_rr;
ds_algorithm = tvb_get_guint8(tvb, cur_offset); ds_algorithm = tvb_get_guint8(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", val_to_str(ds_algorithm, algo_vals,"Unknown (0x%02X)") ); proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", val_to_str(ds_algorithm, algo_vals,"Unknown (0x%02X)") );
cur_offset += 1; cur_offset += 1;
rr_len -= 1; rr_len -= 1;
if (rr_len < 1)
goto bad_rr;
ds_digest = tvb_get_guint8(tvb, cur_offset); ds_digest = tvb_get_guint8(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Digest type: %s", val_to_str(ds_digest, tds_digests, "Unknown (0x%02X)")); proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Digest type: %s", val_to_str(ds_digest, tds_digests, "Unknown (0x%02X)"));
cur_offset += 1; cur_offset += 1;
rr_len -= 1; rr_len -= 1;
if( ds_digest == TDSDIGEST_SHA1 ) digest_data_size = 20; // SHA1 key is always 20 bytes long
if( digest_data_size > 0 ) if (ds_digest == TDSDIGEST_SHA1)
digest_data_size = 20; /* SHA1 key is always 20 bytes long */
if (digest_data_size > 0) {
if (rr_len < digest_data_size)
goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, digest_data_size, "Public key"); proto_tree_add_text(rr_tree, tvb, cur_offset, digest_data_size, "Public key");
}
} }
} }
break; break;
case T_TKEY: case T_TKEY:
{ {
char tkey_algname[MAXDNAME]; char tkey_algname[MAXDNAME];
@ -1675,6 +1718,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += tkey_algname_len; cur_offset += tkey_algname_len;
rr_len -= tkey_algname_len; rr_len -= tkey_algname_len;
if (rr_len < 4)
goto bad_rr;
nstime.secs = tvb_get_ntohl(tvb, cur_offset); nstime.secs = tvb_get_ntohl(tvb, cur_offset);
nstime.nsecs = 0; nstime.nsecs = 0;
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
@ -1682,6 +1727,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
nstime.secs = tvb_get_ntohl(tvb, cur_offset); nstime.secs = tvb_get_ntohl(tvb, cur_offset);
nstime.nsecs = 0; nstime.nsecs = 0;
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
@ -1689,6 +1736,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 2)
goto bad_rr;
tkey_mode = tvb_get_ntohs(tvb, cur_offset); tkey_mode = tvb_get_ntohs(tvb, cur_offset);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
@ -1696,6 +1745,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
val_to_str(tkey_mode, tkey_modes, val_to_str(tkey_mode, tkey_modes,
"Unknown (0x%04X)")); "Unknown (0x%04X)"));
if (rr_len < 2)
goto bad_rr;
tkey_error = tvb_get_ntohs(tvb, cur_offset); tkey_error = tvb_get_ntohs(tvb, cur_offset);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
@ -1748,13 +1799,19 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += tkey_keylen; cur_offset += tkey_keylen;
rr_len -= tkey_keylen; rr_len -= tkey_keylen;
if (rr_len < 2)
goto bad_rr;
tkey_otherlen = tvb_get_ntohs(tvb, cur_offset); tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other"); if (tkey_otherlen != 0) {
cur_offset += tkey_otherlen; if (rr_len < tkey_otherlen)
rr_len -= tkey_otherlen; goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
cur_offset += tkey_otherlen;
rr_len -= tkey_otherlen;
}
} }
} }
break; break;
@ -1776,6 +1833,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += tsig_algname_len; cur_offset += tsig_algname_len;
rr_len -= tsig_algname_len; rr_len -= tsig_algname_len;
if (rr_len < 6)
goto bad_rr;
tsig_timehi = tvb_get_ntohs(tvb, cur_offset); tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2); tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
nstime.secs = tsig_timelo; nstime.secs = tsig_timelo;
@ -1785,26 +1844,38 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 6; cur_offset += 6;
rr_len -= 6; rr_len -= 6;
if (rr_len < 2)
goto bad_rr;
tsig_fudge = tvb_get_ntohs(tvb, cur_offset); tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u", proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
tsig_fudge); tsig_fudge);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
if (rr_len < 2)
goto bad_rr;
tsig_siglen = tvb_get_ntohs(tvb, cur_offset); tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature"); if (tsig_siglen != 0) {
cur_offset += tsig_siglen; if (rr_len < tsig_siglen)
rr_len -= tsig_siglen; goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
cur_offset += tsig_siglen;
rr_len -= tsig_siglen;
}
if (rr_len < 2)
goto bad_rr;
tsig_originalid = tvb_get_ntohs(tvb, cur_offset); tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d", proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
tsig_originalid); tsig_originalid);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
if (rr_len < 2)
goto bad_rr;
tsig_error = tvb_get_ntohs(tvb, cur_offset); tsig_error = tvb_get_ntohs(tvb, cur_offset);
proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
val_to_str(tsig_error, rcode_vals, val_to_str(tsig_error, rcode_vals,
@ -1812,13 +1883,19 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
if (rr_len < 2)
goto bad_rr;
tsig_otherlen = tvb_get_ntohs(tvb, cur_offset); tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
cur_offset += 2; cur_offset += 2;
rr_len -= 2; rr_len -= 2;
proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other"); if (tsig_otherlen != 0) {
cur_offset += tsig_otherlen; if (rr_len < tsig_otherlen)
rr_len -= tsig_otherlen; goto bad_rr;
proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
cur_offset += tsig_otherlen;
rr_len -= tsig_otherlen;
}
} }
} }
break; break;
@ -1832,6 +1909,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
guint32 nservers; guint32 nservers;
if (dns_tree != NULL) { if (dns_tree != NULL) {
if (rr_len < 4)
goto bad_rr;
local_flag = tvb_get_ntohl(tvb, cur_offset); local_flag = tvb_get_ntohl(tvb, cur_offset);
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
@ -1840,6 +1919,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
lookup_timeout = tvb_get_ntohl(tvb, cur_offset); lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
@ -1848,6 +1929,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
cache_timeout = tvb_get_ntohl(tvb, cur_offset); cache_timeout = tvb_get_ntohl(tvb, cur_offset);
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
@ -1856,6 +1939,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
nservers = tvb_get_ntohl(tvb, cur_offset); nservers = tvb_get_ntohl(tvb, cur_offset);
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
@ -1865,6 +1950,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
rr_len -= 4; rr_len -= 4;
while (rr_len != 0 && nservers != 0) { while (rr_len != 0 && nservers != 0) {
if (rr_len < 4)
goto bad_rr;
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
ip_to_str(tvb_get_ptr(tvb, cur_offset, 4))); ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
@ -1886,6 +1973,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
char dname[MAXDNAME]; char dname[MAXDNAME];
int dname_len; int dname_len;
if (rr_len < 4)
goto bad_rr;
local_flag = tvb_get_ntohl(tvb, cur_offset); local_flag = tvb_get_ntohl(tvb, cur_offset);
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
@ -1894,6 +1983,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
lookup_timeout = tvb_get_ntohl(tvb, cur_offset); lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
@ -1902,6 +1993,8 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
cur_offset += 4; cur_offset += 4;
rr_len -= 4; rr_len -= 4;
if (rr_len < 4)
goto bad_rr;
cache_timeout = tvb_get_ntohl(tvb, cur_offset); cache_timeout = tvb_get_ntohl(tvb, cur_offset);
if (dns_tree != NULL) { if (dns_tree != NULL) {
proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds", proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
@ -1959,6 +2052,16 @@ dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
data_offset += data_len; data_offset += data_len;
return data_offset - data_start;
bad_rr:
if (dns_tree != NULL) {
proto_item_append_text(trr, ", bad RR length %d, too short",
data_len);
}
data_offset += data_len;
return data_offset - data_start; return data_offset - data_start;
} }