Source code for synapse.models.dns

import synapse.exc as s_exc

import synapse.lib.types as s_types
import synapse.lib.module as s_module

dnsreplycodes = (
    (0, 'NOERROR'),
    (1, 'FORMERR'),
    (2, 'SERVFAIL'),
    (3, 'NXDOMAIN'),
    (4, 'NOTIMP'),
    (5, 'REFUSED'),
    (6, 'YXDOMAIN'),
    (7, 'YXRRSET'),
    (8, 'NXRRSET'),
    (9, 'NOTAUTH'),
    (10, 'NOTZONE'),
    (11, 'DSOTYPENI'),
    (16, 'BADSIG'),
    (17, 'BADKEY'),
    (18, 'BADTIME'),
    (19, 'BADMODE'),
    (20, 'BADNAME'),
    (21, 'BADALG'),
    (22, 'BADTRUNC'),
    (23, 'BADCOOKIE'),
)

# IANA DNS Resource Record (RR) TYPEs and QTYPEs.
dnsquerytypes = (
    (1, 'A'),
    (2, 'NS'),
    (3, 'MD'),
    (4, 'MF'),
    (5, 'CNAME'),
    (6, 'SOA'),
    (7, 'MB'),
    (8, 'MG'),
    (9, 'MR'),
    (10, 'NULL'),
    (11, 'WKS'),
    (12, 'PTR'),
    (13, 'HINFO'),
    (14, 'MINFO'),
    (15, 'MX'),
    (16, 'TXT'),
    (17, 'RP'),
    (18, 'AFSDB'),
    (19, 'X25'),
    (20, 'ISDN'),
    (21, 'RT'),
    (22, 'NSAP'),
    (23, 'NSAP-PTR'),
    (24, 'SIG'),
    (25, 'KEY'),
    (26, 'PX'),
    (27, 'GPOS'),
    (28, 'AAAA'),
    (29, 'LOC'),
    (30, 'NXT'),
    (31, 'EID'),
    (32, 'NIMLOC'),
    (33, 'SRV'),
    (34, 'ATMA'),
    (35, 'NAPTR'),
    (36, 'KX'),
    (37, 'CERT'),
    (38, 'A6'),
    (39, 'DNAME'),
    (40, 'SINK'),
    (41, 'OPT'),
    (42, 'APL'),
    (43, 'DS'),
    (44, 'SSHFP'),
    (45, 'IPSECKEY'),
    (46, 'RRSIG'),
    (47, 'NSEC'),
    (48, 'DNSKEY'),
    (49, 'DHCID'),
    (50, 'NSEC3'),
    (51, 'NSEC3PARAM'),
    (52, 'TLSA'),
    (53, 'SMIMEA'),
    (55, 'HIP'),
    (56, 'NINFO'),
    (57, 'RKEY'),
    (58, 'TALINK'),
    (59, 'CDS'),
    (60, 'CDNSKEY'),
    (61, 'OPENPGPKEY'),
    (62, 'CSYNC'),
    (63, 'ZONEMD'),
    (64, 'SVCB'),
    (65, 'HTTPS'),
    (99, 'SPF'),
    (100, 'UINFO'),
    (101, 'UID'),
    (102, 'GID'),
    (103, 'UNSPEC'),
    (104, 'NID'),
    (105, 'L32'),
    (106, 'L64'),
    (107, 'LP'),
    (108, 'EUI48'),
    (109, 'EUI64'),
    (249, 'TKEY'),
    (250, 'TSIG'),
    (251, 'IXFR'),
    (252, 'AXFR'),
    (253, 'MAILB'),
    (254, 'MAILA'),
    (255, 'ANY'),
    (256, 'URI'),
    (257, 'CAA'),
    (258, 'AVC'),
    (259, 'DOA'),
    (260, 'AMTRELAY'),
    (261, 'RESINFO'),
    (262, 'WALLET'),
    (263, 'CLA'),
    (264, 'IPN'),
    (32768, 'TA'),
    (32769, 'DLV'),
)

[docs] class DnsName(s_types.Str):
[docs] def postTypeInit(self): s_types.Str.postTypeInit(self) self.inarpa = '.in-addr.arpa' self.inarpa6 = '.ip6.arpa' self.setNormFunc(str, self._normPyStr)
def _normPyStr(self, valu): # Backwards compatible norm = valu.lower() norm = norm.strip() # type: str # Break out fqdn / ipv4 / ipv6 subs :D subs = {} # ipv4 if norm.isnumeric(): # do-nothing for integer only strs pass elif norm.endswith(self.inarpa): # Strip, reverse, check if ipv4 temp = norm[:-len(self.inarpa)] temp = '.'.join(temp.split('.')[::-1]) try: ipv4norm, info = self.modl.type('inet:ipv4').norm(temp) except s_exc.BadTypeValu as e: pass else: subs['ipv4'] = ipv4norm elif norm.endswith(self.inarpa6): parts = [c for c in norm[:-len(self.inarpa6)][::-1] if c != '.'] try: if len(parts) != 32: raise s_exc.BadTypeValu(mesg='Invalid number of ipv6 parts') temp = int(''.join(parts), 16) ipv6norm, info = self.modl.type('inet:ipv6').norm(temp) except s_exc.BadTypeValu as e: pass else: subs['ipv6'] = ipv6norm ipv4 = info.get('subs').get('ipv4') if ipv4 is not None: subs['ipv4'] = ipv4 else: # Try fallbacks to parse out possible ipv4/ipv6 garbage queries try: ipv4norm, info = self.modl.type('inet:ipv4').norm(norm) except s_exc.BadTypeValu as e: try: ipv6norm, info = self.modl.type('inet:ipv6').norm(norm) except s_exc.BadTypeValu as e2: pass else: subs['ipv6'] = ipv6norm ipv4 = info.get('subs').get('ipv4') if ipv4 is not None: subs['ipv4'] = ipv4 else: subs['ipv4'] = ipv4norm # Lastly, try give the norm'd valu a shot as an inet:fqdn try: fqdnnorm, info = self.modl.type('inet:fqdn').norm(norm) except s_exc.BadTypeValu as e: pass else: subs['fqdn'] = fqdnnorm return norm, {'subs': subs}
[docs] class DnsModule(s_module.CoreModule):
[docs] def getModelDefs(self): modl = { 'ctors': ( ('inet:dns:name', 'synapse.models.dns.DnsName', {}, { 'doc': 'A DNS query name string. Likely an FQDN but not always.', 'ex': 'vertex.link', }), ), 'types': ( ('inet:dns:a', ('comp', {'fields': (('fqdn', 'inet:fqdn'), ('ipv4', 'inet:ipv4'))}), { 'ex': '(vertex.link,1.2.3.4)', 'doc': 'The result of a DNS A record lookup.'}), ('inet:dns:aaaa', ('comp', {'fields': (('fqdn', 'inet:fqdn'), ('ipv6', 'inet:ipv6'))}), { 'ex': '(vertex.link,2607:f8b0:4004:809::200e)', 'doc': 'The result of a DNS AAAA record lookup.'}), ('inet:dns:rev', ('comp', {'fields': (('ipv4', 'inet:ipv4'), ('fqdn', 'inet:fqdn'))}), { 'ex': '(1.2.3.4,vertex.link)', 'doc': 'The transformed result of a DNS PTR record lookup.'}), ('inet:dns:rev6', ('comp', {'fields': (('ipv6', 'inet:ipv6'), ('fqdn', 'inet:fqdn'))}), { 'ex': '(2607:f8b0:4004:809::200e,vertex.link)', 'doc': 'The transformed result of a DNS PTR record for an IPv6 address.'}), ('inet:dns:ns', ('comp', {'fields': (('zone', 'inet:fqdn'), ('ns', 'inet:fqdn'))}), { 'ex': '(vertex.link,ns.dnshost.com)', 'doc': 'The result of a DNS NS record lookup.'}), ('inet:dns:cname', ('comp', {'fields': (('fqdn', 'inet:fqdn'), ('cname', 'inet:fqdn'))}), { 'ex': '(foo.vertex.link,vertex.link)', 'doc': 'The result of a DNS CNAME record lookup.'}), ('inet:dns:mx', ('comp', {'fields': (('fqdn', 'inet:fqdn'), ('mx', 'inet:fqdn'))}), { 'ex': '(vertex.link,mail.vertex.link)', 'doc': 'The result of a DNS MX record lookup.'}), ('inet:dns:soa', ('guid', {}), { 'doc': 'The result of a DNS SOA record lookup.'}), ('inet:dns:txt', ('comp', {'fields': (('fqdn', 'inet:fqdn'), ('txt', 'str'))}), { 'ex': '(hehe.vertex.link,"fancy TXT record")', 'doc': 'The result of a DNS TXT record lookup.'}), ('inet:dns:type', ('int', {}), { 'doc': 'A DNS query/answer type integer.'}), ('inet:dns:query', ('comp', {'fields': (('client', 'inet:client'), ('name', 'inet:dns:name'), ('type', ('int', {'enums': dnsquerytypes, 'enums:strict': False})))}), { 'ex': '(1.2.3.4, woot.com, 1)', 'doc': 'A DNS query unique to a given client.'}), ('inet:dns:request', ('guid', {}), { 'doc': 'A single instance of a DNS resolver request and optional reply info.'}), ('inet:dns:answer', ('guid', {}), { 'doc': 'A single answer from within a DNS reply.'}), ('inet:dns:wild:a', ('comp', {'fields': (('fqdn', 'inet:fqdn'), ('ipv4', 'inet:ipv4'))}), { 'doc': 'A DNS A wild card record and the IPv4 it resolves to.'}), ('inet:dns:wild:aaaa', ('comp', {'fields': (('fqdn', 'inet:fqdn'), ('ipv6', 'inet:ipv6'))}), { 'doc': 'A DNS AAAA wild card record and the IPv6 it resolves to.'}), ('inet:dns:dynreg', ('guid', {}), { 'doc': 'A dynamic DNS registration.'}), ), 'forms': ( ('inet:dns:a', {}, ( ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain queried for its DNS A record.'}), ('ipv4', ('inet:ipv4', {}), {'ro': True, 'doc': 'The IPv4 address returned in the A record.'}), )), ('inet:dns:aaaa', {}, ( ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain queried for its DNS AAAA record.'}), ('ipv6', ('inet:ipv6', {}), {'ro': True, 'doc': 'The IPv6 address returned in the AAAA record.'}), )), ('inet:dns:rev', {}, ( ('ipv4', ('inet:ipv4', {}), {'ro': True, 'doc': 'The IPv4 address queried for its DNS PTR record.'}), ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain returned in the PTR record.'}), )), ('inet:dns:rev6', {}, ( ('ipv6', ('inet:ipv6', {}), {'ro': True, 'doc': 'The IPv6 address queried for its DNS PTR record.'}), ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain returned in the PTR record.'}), )), ('inet:dns:ns', {}, ( ('zone', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain queried for its DNS NS record.'}), ('ns', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain returned in the NS record.'}), )), ('inet:dns:cname', {}, ( ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain queried for its CNAME record.'}), ('cname', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain returned in the CNAME record.'}), )), ('inet:dns:mx', {}, ( ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain queried for its MX record.'}), ('mx', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain returned in the MX record.'}), )), ('inet:dns:soa', {}, ( ('fqdn', ('inet:fqdn', {}), { 'doc': 'The domain queried for its SOA record.'}), ('ns', ('inet:fqdn', {}), { 'doc': 'The domain (MNAME) returned in the SOA record.'}), ('email', ('inet:email', {}), { 'doc': 'The email address (RNAME) returned in the SOA record.'}), )), ('inet:dns:txt', {}, ( ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain queried for its TXT record.'}), ('txt', ('str', {}), {'ro': True, 'doc': 'The string returned in the TXT record.'}), )), ('inet:dns:query', {}, ( ('client', ('inet:client', {}), {'ro': True, }), ('name', ('inet:dns:name', {}), {'ro': True, }), ('name:ipv4', ('inet:ipv4', {}), {}), ('name:ipv6', ('inet:ipv6', {}), {}), ('name:fqdn', ('inet:fqdn', {}), {}), ('type', ('int', {'enums': dnsquerytypes, 'enums:strict': False}), {'ro': True, }), )), ('inet:dns:request', {}, ( ('time', ('time', {}), {}), ('query', ('inet:dns:query', {}), {}), ('query:name', ('inet:dns:name', {}), {}), ('query:name:ipv4', ('inet:ipv4', {}), {}), ('query:name:ipv6', ('inet:ipv6', {}), {}), ('query:name:fqdn', ('inet:fqdn', {}), {}), ('query:type', ('int', {'enums': dnsquerytypes, 'enums:strict': False}), {}), ('server', ('inet:server', {}), {}), ('reply:code', ('int', {'enums': dnsreplycodes, 'enums:strict': False}), { 'doc': 'The DNS server response code.'}), ('exe', ('file:bytes', {}), { 'doc': 'The file containing the code that attempted the DNS lookup.'}), ('proc', ('it:exec:proc', {}), { 'doc': 'The process that attempted the DNS lookup.'}), ('host', ('it:host', {}), { 'doc': 'The host that attempted the DNS lookup.'}), ('sandbox:file', ('file:bytes', {}), { 'doc': 'The initial sample given to a sandbox environment to analyze.'}), )), ('inet:dns:answer', {}, ( ('ttl', ('int', {}), {}), ('request', ('inet:dns:request', {}), {}), ('a', ('inet:dns:a', {}), { 'doc': 'The DNS A record returned by the lookup.'}), ('ns', ('inet:dns:ns', {}), { 'doc': 'The DNS NS record returned by the lookup.'}), ('rev', ('inet:dns:rev', {}), { 'doc': 'The DNS PTR record returned by the lookup.'}), ('aaaa', ('inet:dns:aaaa', {}), { 'doc': 'The DNS AAAA record returned by the lookup.'}), ('rev6', ('inet:dns:rev6', {}), { 'doc': 'The DNS PTR record returned by the lookup of an IPv6 address.'}), ('cname', ('inet:dns:cname', {}), { 'doc': 'The DNS CNAME record returned by the lookup.'}), ('mx', ('inet:dns:mx', {}), { 'doc': 'The DNS MX record returned by the lookup.'}), ('mx:priority', ('int', {}), { 'doc': 'The DNS MX record priority.'}), ('soa', ('inet:dns:soa', {}), { 'doc': 'The domain queried for its SOA record.'}), ('txt', ('inet:dns:txt', {}), { 'doc': 'The DNS TXT record returned by the lookup.'}), ('time', ('time', {}), { 'doc': 'The time that the DNS response was transmitted.'}), )), ('inet:dns:wild:a', {}, ( ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain containing a wild card record.'}), ('ipv4', ('inet:ipv4', {}), {'ro': True, 'doc': 'The IPv4 address returned by wild card resolutions.'}), )), ('inet:dns:wild:aaaa', {}, ( ('fqdn', ('inet:fqdn', {}), {'ro': True, 'doc': 'The domain containing a wild card record.'}), ('ipv6', ('inet:ipv6', {}), {'ro': True, 'doc': 'The IPv6 address returned by wild card resolutions.'}), )), ('inet:dns:dynreg', {}, ( ('fqdn', ('inet:fqdn', {}), { 'doc': 'The FQDN registered within a dynamic DNS provider.'}), ('provider', ('ou:org', {}), { 'doc': 'The organization which provides the dynamic DNS FQDN.'}), ('provider:name', ('ou:name', {}), { 'doc': 'The name of the organization which provides the dynamic DNS FQDN.'}), ('provider:fqdn', ('inet:fqdn', {}), { 'doc': 'The FQDN of the organization which provides the dynamic DNS FQDN.'}), ('contact', ('ps:contact', {}), { 'doc': 'The contact information of the registrant.'}), ('created', ('time', {}), { 'doc': 'The time that the dynamic DNS registration was first created.'}), ('client', ('inet:client', {}), { 'doc': 'The network client address used to register the dynamic FQDN.'}), ('client:ipv4', ('inet:ipv4', {}), { 'doc': 'The client IPv4 address used to register the dynamic FQDN.'}), ('client:ipv6', ('inet:ipv6', {}), { 'doc': 'The client IPv6 address used to register the dynamic FQDN.'}), )), ) } name = 'inet:dns' return ((name, modl), )