On Wednesday, April 10, 2019 12:36:34 PM Dave Crocker wrote:
> Folks,
> 
> Howdy.
> 
> I'm trying to get a bit of education about reality.  Always dangerous,
> but I've no choice...
> 
> 
> For the software you know about, how are queries to the DNS performed,
> to obtain the TXT records associated with DKIM and/or DMARC?
> 
> I'm trying to understand the breadth and limitations of returned
> information that is filtered or passed by the code that is actually in
> use.  Which libraries and which calls from those libraries.

I'm most familiar with how it's done with dkimpy (Python DKIM library) [1].  
It uses an internal abstraction layer (we call dnsplug) to that the module 
itself works with either pydns/py3dns [2] or dnspython.  I'm not sure exactly 
what you're after here, but  the code's simple enough, so here it is:

def get_txt_dnspython(name):
    """Return a TXT record associated with a DNS name."""
    try:
      a = dns.resolver.query(name, dns.rdatatype.TXT,raise_on_no_answer=False)
      for r in a.response.answer:
          if r.rdtype == dns.rdatatype.TXT:
              return b"".join(r.items[0].strings)
    except dns.resolver.NXDOMAIN: pass
    return None


def get_txt_pydns(name):
    """Return a TXT record associated with a DNS name."""
    # Older pydns releases don't like a trailing dot.
    if name.endswith('.'):
        name = name[:-1]
    response = DNS.DnsRequest(name, qtype='txt').req()
    if not response.answers:
        return None
    return b''.join(response.answers[0]['data'])

There is a detection process that will decide what to use and then define 
dnsplug.get_txt as the appropriate variant.

Not being sure how far you want to take this, here's an example of a TXT query 
using pydns or py3dns (I picked this one because it has multiple TXT records):

Code:

>>> import DNS
>>> response = DNS.DnsRequest('google.com', qtype='txt').req()
>>> print(response.answers)

Result (whitespace added for clarity):
[
{'classstr': 'IN', 'ttl': 299, 'rdlength': 46, 'class': 1, 'typename': 'TXT', 
'data': [b'docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e'], 'name': 
'google.com', 'type': 16},
 
{'classstr': 'IN', 'ttl': 3599, 'rdlength': 36, 'class': 1, 'typename': 'TXT', 
'data': [b'v=spf1 include:_spf.google.com ~all'], 'name': 'google.com', 
'type': 16}, 

{'classstr': 'IN', 'ttl': 3599, 'rdlength': 60, 'class': 1, 'typename': 'TXT', 
'data': [b'facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95'], 
'name': 'google.com', 'type': 16}, 

{'classstr': 'IN', 'ttl': 3599, 'rdlength': 65, 'class': 1, 'typename': 'TXT', 
'data': [b'globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8='], 
'name': 'google.com', 'type': 16}
]

For completeness, here's the balance of what you can pull out of the response 
object for this request:

>>> print(response.header)
{'ra': 1, 'qdcount': 1, 'opcode': 0, 'id': 46730, 'tc': 0, 'nscount': 0, 
'arcount': 0, 'z': 0, 'ancount': 4, 'aa': 0, 'status': 'NOERROR', 'qr': 1, 
'rd': 1, 'opcodestr': 'QUERY', 'rcode': 0}

>>> print(response.questions)
[{'qname': 'google.com', 'qtypestr': 'TXT', 'qclassstr': 'IN', 'qclass': 1, 
'qtype': 16}]

>>> print(response.authority)
[]

>>> print(response.additional)
[]

>>> print(response.args)
{'qtype': 'txt', 'port': 53, 'protocol': 'udp', 'elapsed': 95.10970115661621, 
'opcode': 0, 'server_rotate': 0, 'rd': 1, 'timeout': 30, 'timing': 1, 'name': 
'google.com', 'server': '127.0.1.1'}

What gets returned to the application from dnsplug is a list of the TXT data.  
In this case:

[b'docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e', b'v=spf1 
include:_spf.google.com ~all', b'facebook-domain-
verification=22rm551cu4k0ab0bxsw536tlds4h95', b'globalsign-smime-
dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8=']

Is that the kind of thing you're after?

Scott K

[1] https://git.launchpad.net/dkimpy/tree/dkim/dnsplug.py

[2] For pydns/py3dns there are separate code bases for python2 and python3, 
but the calls are the same.

_______________________________________________
dmarc mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/dmarc

Reply via email to