Here is a debdiff for Etch. In addition to fixing this regression, I also switched DNS/Base.py to use the upstream fix for the DNS cache poisoning problem. Their fix is more robust. If you'd rather just deal with this exact problem, drop the changes in DNS/Base.py. The fix for this problem is the one liner in DNS/Lib.py.
Scott K
diff -u python-dns-2.3.0/DNS/Base.py python-dns-2.3.0/DNS/Base.py
--- python-dns-2.3.0/DNS/Base.py
+++ python-dns-2.3.0/DNS/Base.py
@@ -140,16 +140,15 @@
# Lib.dumpM(u)
def getSource(self):
- # Get random source port to avoid DNS cache poisoning attack.
- try:
- source = random.randint(1024,65535)
- self.s.bind(('', source))
- except socket.error, msg:
- # Error 98, 'Address already in use'
- if msg[0] == 98:
- self.getSource()
- else:
- raise
+ "Pick random source port to avoid DNS cache poisoning attack."
+ while True:
+ try:
+ source_port = random.randint(1024,65535)
+ self.s.bind(('', source_port))
+ break
+ except socket.error, msg:
+ # Error 98, 'Address already in use'
+ if msg[0] != 98: raise
def conn(self):
# Source is source port we'll take a reply from.
@@ -207,25 +206,25 @@
try:
try:
# TODO. Handle timeouts &c correctly (RFC)
- #self.s.connect((self.ns, self.port))
- self.conn()
- self.s.setblocking(0)
self.time_start=time.time()
+ self.conn()
if not self.async:
self.s.send(self.request)
r=self.processUDPReply()
- # Since we bind to the source port, we don't need to check that
- # here, but do make sure it's actually a DNS request that the packet
- # is in reply to.
- while r.header['id'] != self.tid or self.from_address[1] != 53:
- r=self.processUDPReply()
+ # Since we bind to the source port and connect to the
+ # destination port, we don't need to check that here,
+ # but do make sure it's actually a DNS request that the
+ # packet is in reply to.
+ while r.header['id'] != self.tid \
+ or self.from_address[1] != self.port:
+ r=self.processUDPReply()
self.response = r
# FIXME: check waiting async queries
- #except socket.error:
- except None:
- continue
- finally:
- self.s.close()
+ finally:
+ if not self.async:
+ self.s.close()
+ except socket.error:
+ continue
break
if not self.response:
if not self.async:
@@ -241,19 +240,21 @@
self.socketInit(socket.AF_INET, socket.SOCK_STREAM)
self.time_start=time.time()
self.conn()
+ buf = Lib.pack16bit(len(self.request))+self.request
+ # Keep server from making sendall hang
self.s.setblocking(0)
- self.s.sendall(Lib.pack16bit(len(self.request))+self.request)
+ # FIXME: throws WOULDBLOCK if request too large to fit in
+ # system buffer
+ self.s.sendall(buf)
self.s.shutdown(socket.SHUT_WR)
r=self.processTCPReply()
- if r.header['id'] != self.tid: continue
- self.response = r
- except socket.error:
- continue
- finally:
- self.s.close()
- break
- if not self.response:
- raise DNSError,'no working nameservers found'
+ if r.header['id'] == self.tid:
+ self.response = r
+ break
+ finally:
+ self.s.close()
+ except socket.error:
+ continue
#class DnsAsyncRequest(DnsRequest):
class DnsAsyncRequest(DnsRequest,asyncore.dispatcher_with_send):
diff -u python-dns-2.3.0/debian/changelog python-dns-2.3.0/debian/changelog
--- python-dns-2.3.0/debian/changelog
+++ python-dns-2.3.0/debian/changelog
@@ -1,3 +1,12 @@
+python-dns (2.3.0-5.2+etch2) stable-security; urgency=medium
+
+ * Non-maintainer upload by the security team;
+ * Modify DNS/Lib.py so unicode DNS names don't cause a crash
+ (Closes: #499277)
+ * Update DNS/Base.py changes for #490217 to more robust upstream fix
+
+ -- Scott Kitterman <[EMAIL PROTECTED]> Wed, 17 Sep 2008 14:01:41 -0400
+
python-dns (2.3.0-5.2+etch1) stable-security; urgency=high
* Non-maintainer upload by the security team; thanks to Scott Kitterman
only in patch2:
unchanged:
--- python-dns-2.3.0.orig/DNS/Lib.py
+++ python-dns-2.3.0/DNS/Lib.py
@@ -99,6 +99,7 @@
list = []
for label in string.splitfields(name, '.'):
if label:
+ label = label.encode('utf8')
if len(label) > 63:
raise PackError, 'label too long'
list.append(label)
signature.asc
Description: This is a digitally signed message part.

