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.