# dnsRegRec-0.8.py 8/15/05 David MacQuigg # import DNS # from pydns.sourceforge.net from DNS import DNSError class Timeout(DNSError): "Special handling for timeouts" class NoRecord(DNSError): "Special handliing for missing records" DNSTimeout = 5 def getTXT(name): '''Get a single TXT record, which might have multiple strings, and return one long string. Raise 'Timeout' for DNS timeout errors, 'NoRecord' for no TXT records or non-existent domain, and DNSError for all other errors. Raise a DNSError if the number of TXT records is greater than one. >>> getTXT('simple.tld.id.open-mail.org') 'svc=S1:A,M2:A,H1:B ip4=192.168.0.0/29' >>> getTXT('nonexistent.tld.id.open-mail.org') Traceback (most recent call last): - - - NoRecord: No TXT record for 'nonexistent.tld.id.open-mail.org'. ''' if name == 'example.com.id.open-mail.org': # stub for local testing return "svc=S1:A,H1:B ip4=192.168.0.0/16" try: reqobj = DNS.Request(name, qtype='TXT', timeout=DNSTimeout) resp = reqobj.req() except DNSError, expln: exp = str(expln) if exp == 'Timeout': raise Timeout, ( "Timeout getting Registry record '%s'." % name ) else: raise DNSError, expln lr = len(resp.answers) if lr == 0: raise NoRecord, ( "No TXT record for '%s'." % name ) # or non-existent domain if lr > 1: raise DNSError, ( "Found %s TXT records for '%s'. Should be 1." % (lr, name) ) ra0 = resp.answers[0] rad = ra0['data'] # list of strings, each < 255 bytes data = ''.join(rad) # concatenate multiple strings ## rdlen = ra0['rdlength'] # total length of data in first record return data if __name__ == '__main__': ##DNS.DiscoverNameServers() # from /etc/resolv.conf or Windows Registry ## # to DNS.defaults # Alternative manual setting: DNS.defaults['server'] = ['216.183.68.110', '216.183.68.111'] import sys, doctest doctest.testmod(sys.modules['__main__'], verbose=True) # More unit tests: # Note: We are not running these via doctest, because there are frequent # changes in the records, which will trigger numerous doctest discrepancies. # Just run them and observe the normal output (quoted below). # You can test a timeout error by setting DNSTimeout to 0.01. ### Note: Setting the Timeout this low causes syncronization problems. # Late arriving records get associated with names later in the list. !!! def test_getTXT(name): try: return getTXT(name) except DNSError, expln: return expln print 40 * '=', 'Declared IDs' namelist = ['simple', 'complex', 'spf-only', 'csv-only', 'rr', '2-strings', '2-txt', 'notxt', 'nonexistant'] for name in namelist: fullname = name + '.tld.id.open-mail.org' record = test_getTXT(fullname) print fullname print record print # Default IDs are stored in a different branch of the Registry. Notice how # we can have different defaults at different levels of the same ID. Every # server in Texas gets a default ID=rr.tld, except servers in Dallas, which # get a default ID=texas.rr.tld. print 40 * '=', 'Default IDs' namelist = ['abilene.texas.rr.tld', 'a.b.c.dallas.texas.rr.tld'] for name in namelist: fullname = name + '.df.open-mail.org' record = test_getTXT(fullname) print fullname print record print # Default IDs can also be determined from the IP address. print 40 * '=', 'Default ID from IP address' fullname = '1.0.168.192.ip.open-mail.org' record = test_getTXT(fullname) print fullname print record print ''' ======================================== Declared IDs simple.tld.id.open-mail.org svc=S1:A,M2:A,H1:B ip4=192.168.0.0/29 complex.tld.id.open-mail.org svc=S1:A,M2:A,H1+:B meth=SPF+5,DK SPF='v=spf1 mx include:s._spf.test.tld include:m._spf.test.tld include:p._spf.test.tld include:c._spf.test.tld ~all' DK=k=rsa;p=HwwDQYJKoZIhvcNAQEBBQADawAwaAJhAKJ2lzDLZ8XlVambQfMXn3LRGKOD5wDQYJKQYJKoZIhvcNAQEBBQADawABgc spf-only.tld.id.open-mail.org svc=S1:A,M2:A,H1:B meth=spf+10 spf='v=spf1 redirect=_spf.open-mail.org' csv-only.tld.id.open-mail.org svc=S1:A,M2:A,H1:B meth=csv+3 rr.tld.id.open-mail.org svc=S1:A,M2:A,H1:B meth=spf+1 spf='v=spf1 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 ip4:192.168.0.0/24 +mx ~all' 2-strings.tld.id.open-mail.org xxx255x89012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345xxx124x890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 2-txt.tld.id.open-mail.org Found 2 TXT records for '2-txt.tld.id.open-mail.org'. Should be 1. notxt.tld.id.open-mail.org No TXT record for 'notxt.tld.id.open-mail.org'. nonexistant.tld.id.open-mail.org No TXT record for 'nonexistant.tld.id.open-mail.org'. ======================================== Default IDs abilene.texas.rr.tld.df.open-mail.org ID=rr.tld score=5 ip4=192.0.4.0/24 a.b.c.dallas.texas.rr.tld.df.open-mail.org ID=texas.rr.tld score=5 ip4=192.0.3.0/24 ======================================== Default ID from IP address 1.0.168.192.ip.open-mail.org ID=192.168.0.1/22 score=5 >>> '''