]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/contrib/unbound-querycachedb.py
Fix multiple vulnerabilities in unbound.
[FreeBSD/FreeBSD.git] / contrib / unbound / contrib / unbound-querycachedb.py
1 #!/usr/bin/env python
2
3 import hashlib
4 import sys
5 import struct
6 import socket
7 import time
8 from optparse import OptionParser
9
10 import dns.message
11 import dns.name
12 import dns.rdataclass
13 import dns.rdatatype
14
15 def _calc_hashkey(qname, secret, qtype):
16     qclass = 'IN'           # CLASS is fixed for simplicity
17     hobj = hashlib.sha256()
18     hobj.update(dns.name.from_text(qname).to_wire())
19     hobj.update(struct.pack('HH',
20                             socket.htons(dns.rdatatype.from_text(qtype)),
21                             socket.htons(dns.rdataclass.from_text(qclass))))
22     hobj.update(secret)
23     return hobj.hexdigest().upper()
24
25 def _redis_get(options, key):
26     import redis
27     return redis.Redis(options.address, int(options.port)).get(key)
28
29 def _dump_value(options, qname, key, value):
30     print(';; query=%s/IN/%s' % (qname, options.qtype))
31     print(';; key=%s' % key)
32     if value is None:
33         print(';; no value')
34         return
35     if len(value) < 16:
36         print(';; broken value, short length: %d' % len(value))
37         return
38     now = int(time.time())
39     timestamp = struct.unpack('!Q', value[-16:-8])[0]
40     expire = struct.unpack('!Q', value[-8:])[0]
41     print(';; Now=%d, TimeStamp=%d, Expire=%d, TTL=%d' %
42           (now, timestamp, expire, max(expire - now, 0)))
43     print(dns.message.from_wire(value[:-16]))
44
45 def main():
46     parser = OptionParser(usage='usage: %prog [options] query_name')
47     parser.add_option("-a", "--address", dest="address", action="store",
48                       default='127.0.0.1', help="backend-server address",
49                       metavar='ADDRESS')
50     parser.add_option("-b", "--backend", dest="backend", action="store",
51                       default='redis', help="backend name",
52                       metavar='BACKEND')
53     parser.add_option("-p", "--port", dest="port", action="store",
54                       default='6379', help="backend-server port",
55                       metavar='PORT')
56     parser.add_option("-s", "--secret", dest="secret", action="store",
57                       default='default', help="secret seed", metavar='SECRET')
58     parser.add_option("-t", "--qtype", dest="qtype", action="store",
59                       default='A', help="query RR type", metavar='QTYPE')
60
61     (options, args) = parser.parse_args()
62     if len(args) < 1:
63         parser.error('qname is missing')
64     if options.backend == 'redis':
65         get_func = _redis_get
66     else:
67         raise Exception('unknown backend name: %s\n' % options.backend)
68     key = _calc_hashkey(args[0], options.secret, options.qtype)
69     value = get_func(options, key)
70     _dump_value(options, args[0], key, value)
71
72 if __name__ == '__main__':
73     try:
74         main()
75     except Exception as e:
76         sys.stderr.write('%s\n' % e)
77         exit(1)