Skip to content

Commit 0ebe567

Browse files
authored
DNS AM: add a bit of defensive programming (#4092)
This fixes #4090
1 parent cd01ec1 commit 0ebe567

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

scapy/layers/dns.py

+31-4
Original file line numberDiff line numberDiff line change
@@ -1520,13 +1520,37 @@ def make_reply(self, req):
15201520
if IPv6 in req:
15211521
resp[IPv6].underlayer.remove_payload()
15221522
resp /= IPv6(dst=req[IPv6].src, src=self.src_ip6 or req[IPv6].dst)
1523-
else:
1523+
elif IP in req:
15241524
resp[IP].underlayer.remove_payload()
15251525
resp /= IP(dst=req[IP].src, src=self.src_ip or req[IP].dst)
1526-
resp /= UDP(sport=req.dport, dport=req.sport)
1526+
else:
1527+
warning("No IP or IPv6 layer in %s", req.command())
1528+
return
1529+
try:
1530+
resp /= UDP(sport=req[UDP].dport, dport=req[UDP].sport)
1531+
except IndexError:
1532+
warning("No UDP layer in %s", req.command(), exc_info=True)
1533+
return
15271534
ans = []
1528-
req = req.getlayer(self.cls)
1529-
for rq in req.qd:
1535+
try:
1536+
req = req[self.cls]
1537+
except IndexError:
1538+
warning(
1539+
"No %s layer in %s",
1540+
self.cls.__name__,
1541+
req.command(),
1542+
exc_info=True,
1543+
)
1544+
return
1545+
try:
1546+
queries = req.qd
1547+
except AttributeError:
1548+
warning("No qd attribute in %s", req.command(), exc_info=True)
1549+
return
1550+
for rq in queries:
1551+
if isinstance(rq, Raw):
1552+
warning("Cannot parse qd element %s", rq.command(), exc_info=True)
1553+
continue
15301554
if rq.qtype in [1, 28]:
15311555
# A or AAAA
15321556
if rq.qtype == 28:
@@ -1598,6 +1622,9 @@ def make_reply(self, req):
15981622
# Error
15991623
break
16001624
else:
1625+
if not ans:
1626+
# No rq was actually answered, as none was valid. Discard.
1627+
return
16011628
# All rq were answered
16021629
resp /= self.cls(id=req.id, qr=1, qd=req.qd, an=ans)
16031630
return resp

test/answering_machines.uts

+7
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ test_am(DNS_am,
119119
match={"google.com": ("127.0.0.1", "::1"), "gaagle.com": "128.0.0.1"},
120120
joker=False)
121121

122+
assert DNS_am().make_reply(Ether()) is None
123+
assert DNS_am().make_reply(Ether()/IP()) is None
124+
assert DNS_am().make_reply(Ether()/IP()/UDP()) is None
125+
assert DNS_am().make_reply(
126+
Ether()/IP()/UDP()/DNS(b'q\xa04\x00\x00\xa0\x01\x00\xf3\x00\x01\x04\x01y')
127+
) is None
128+
122129
= DHCPv6_am - Basic Instantiaion
123130
~ osx netaccess
124131
a = DHCPv6_am()

0 commit comments

Comments
 (0)