From 3a2e5fef612798f7936477fa035c9ec93530e83b Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Mon, 29 Oct 2018 21:49:39 -0400 Subject: [PATCH] Delete unused copy of dnsplug.py --- dnsplug.py | 168 ----------------------------------------------------- 1 file changed, 168 deletions(-) delete mode 100644 dnsplug.py diff --git a/dnsplug.py b/dnsplug.py deleted file mode 100644 index aa357ec..0000000 --- a/dnsplug.py +++ /dev/null @@ -1,168 +0,0 @@ -## @package dnsplug -# Provide a higher level interface to pydns or dnspython (or other provider). -# NOT RELEASED: this is a proposed API and implementation. -# Goals - work with both pydns and dnspython (and possibly other libraries) -# at a simplied level. -# TODO: -# 1. map exceptions to common dnsplug.DNSError exception (with -# original exception saved as a member). -# 2. include dict based implementation (handy for test suites) -# 3. move implementations to subpackages to enable autoselect on first call. - -## Maximum number of CNAME records to follow -MAX_CNAME = 10 - -## Lookup DNS records by label and RR type. -# The response can include records of other types that the DNS -# server thinks we might need. FIXME: empty result -# could mean NXDOMAIN or NOANSWER. -# @param name the DNS label to lookup -# @param qtype the name of the DNS RR type to lookup -# @param tcpfallback if False, raise exception instead of TCP fallback -# @return a list of ((name,type),data) tuples -def DNSLookup(name, qtype, tcpfallback=True, timeout=30): - raise NotImplementedError('No supported dns library found') - -class Session(object): - """A Session object has a simple cache with no TTL that is valid - for a single "session", for example an SMTP conversation.""" - def __init__(self): - self.cache = {} - - ## Additional DNS RRs we can safely cache. - # We have to be careful which additional DNS RRs we cache. For - # instance, PTR records are controlled by the connecting IP, and they - # could poison our local cache with bogus A and MX records. - # Each entry is a tuple of (query_type,rr_type). So for instance, - # the entry ('MX','A') says it is safe (for milter purposes) to cache - # any 'A' RRs found in an 'MX' query. - SAFE2CACHE = frozenset(( - ('MX','MX'), ('MX','A'), - ('CNAME','CNAME'), ('CNAME','A'), - ('A','A'), - ('AAAA','AAAA'), - ('PTR','PTR'), - ('NS','NS'), ('NS','A'), - ('TXT','TXT'), - ('SPF','SPF') - )) - - ## Cached DNS lookup. - # @param name the DNS label to query - # @param qtype the query type, e.g. 'A' - # @param cnames tracks CNAMES already followed in recursive calls - def dns(self, name, qtype, cnames=None): - """DNS query. - - If the result is in cache, return that. Otherwise pull the - result from DNS, and cache ALL answers, so additional info - is available for further queries later. - - CNAMEs are followed. - - If there is no data, [] is returned. - - pre: qtype in ['A', 'AAAA', 'MX', 'PTR', 'TXT', 'SPF'] - post: isinstance(__return__, types.ListType) - """ - result = self.cache.get( (name, qtype) ) - cname = None - - if not result: - safe2cache = Session.SAFE2CACHE - for k, v in DNSLookup(name, qtype): - if k == (name, 'CNAME'): - cname = v - if (qtype,k[1]) in safe2cache: - self.cache.setdefault(k, []).append(v) - result = self.cache.get( (name, qtype), []) - if not result and cname: - if not cnames: - cnames = {} - elif len(cnames) >= MAX_CNAME: - #return result # if too many == NX_DOMAIN - raise DNSError('Length of CNAME chain exceeds %d' % MAX_CNAME) - cnames[name] = cname - if cname in cnames: - raise DNSError, 'CNAME loop' - result = self.dns(cname, qtype, cnames=cnames) - return result - -def DNSLookup_pydns(name, qtype, tcpfallback=True, timeout=30): - try: - # FIXME: To be thread safe, we create a fresh DnsRequest with - # each call. It would be more efficient to reuse - # a req object stored in a Session. - req = DNS.DnsRequest(name, qtype=qtype, timeout=timeout) - resp = req.req() - #resp.show() - # key k: ('wayforward.net', 'A'), value v - # FIXME: pydns returns AAAA RR as 16 byte binary string, but - # A RR as dotted quad. For consistency, this driver should - # return both as binary string. - # - if resp.header['tc'] == True: - if not tcpfallback: - raise DNS.DNSError, 'DNS: Truncated UDP Reply, SPF records should fit in a UDP packet' - try: - req = DNS.DnsRequest(name, qtype=qtype, protocol='tcp', - timeout=timeout) - resp = req.req() - except DNS.DNSError, x: - raise DNS.DNSError, 'TCP Fallback error: ' + str(x) - return [((a['name'], a['typename']), a['data']) for a in resp.answers] - except IOError, x: - raise DNS.DNSError, 'DNS: ' + str(x) - -def DNSLookup_dnspython(name,qtype,tcpfallback=True,timeout=30): - retVal = [] - try: - # FIXME: how to disable TCP fallback in dnspython if not tcpfallback? - answers = dns.resolver.query(name, qtype) - for rdata in answers: - if qtype == 'A' or qtype == 'AAAA': - retVal.append(((name, qtype), rdata.address)) - elif qtype == 'MX': - retVal.append(((name, qtype), (rdata.preference, rdata.exchange))) - elif qtype == 'PTR': - retVal.append(((name, qtype), rdata.target.to_text(True))) - elif qtype == 'TXT' or qtype == 'SPF': - retVal.append(((name, qtype), rdata.strings)) - except dns.resolver.NoAnswer: - pass - except dns.resolver.NXDOMAIN: - pass - return retVal - -try: - # prefer dnspython (the more complete library) - import dns - import dns.resolver # http://www.dnspython.org - import dns.exception - - if not hasattr(dns.rdatatype,'SPF'): - # patch in type99 support - dns.rdatatype.SPF = 99 - dns.rdatatype._by_text['SPF'] = dns.rdatatype.SPF - - DNSLookup = DNSLookup_dnspython -except: - import DNS # http://pydns.sourceforge.net - - if not hasattr(DNS.Type, 'SPF'): - # patch in type99 support - DNS.Type.SPF = 99 - DNS.Type.typemap[99] = 'SPF' - DNS.Lib.RRunpacker.getSPFdata = DNS.Lib.RRunpacker.getTXTdata - - # Fails on Mac OS X? Add domain to /etc/resolv.conf - DNS.DiscoverNameServers() - - DNSLookup = DNSLookup_pydns - -if __name__ == '__main__': - import sys - s = Session() - for n,t in zip(*[iter(sys.argv[1:])]*2): - print n,t - print s.dns(n,t)