Package lib :: Package cuckoo :: Package common :: Module dns
[hide private]
[frames] | no frames]

Source Code for Module lib.cuckoo.common.dns

  1  # Copyright (C) 2010-2013 Claudio Guarnieri. 
  2  # Copyright (C) 2014-2016 Cuckoo Foundation. 
  3  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  4  # See the file 'docs/LICENSE' for copying permission. 
  5   
  6  import select 
  7  import socket 
  8  import threading 
  9   
 10  try: 
 11      import pycares 
 12      HAVE_CARES = True 
 13  except: 
 14      HAVE_CARES = False 
 15   
 16  #try: 
 17  #    import gevent, gevent.socket 
 18  #    HAVE_GEVENT = True 
 19  #except: 
 20  HAVE_GEVENT = False 
 21   
 22   
 23  # these are used by all resolvers 
 24  DNS_TIMEOUT = 5 
 25  DNS_TIMEOUT_VALUE = "" 
 26   
27 -def set_timeout(value):
28 global DNS_TIMEOUT 29 DNS_TIMEOUT = value
30
31 -def set_timeout_value(value):
32 global DNS_TIMEOUT_VALUE 33 DNS_TIMEOUT_VALUE = value
34 35 36 # standard gethostbyname in thread 37 # http://code.activestate.com/recipes/473878/
38 -def with_timeout(func, args=(), kwargs={}):
39 """This function will spawn a thread and run the given function 40 using the args, kwargs and return the given default value if the 41 timeout_duration is exceeded. 42 """ 43 class ResultThread(threading.Thread): 44 daemon = True 45 def __init__(self): 46 threading.Thread.__init__(self) 47 self.result, self.error = None, None
48 def run(self): 49 try: 50 self.result = func(*args, **kwargs) 51 except Exception, e: 52 self.error = e 53 54 it = ResultThread() 55 it.start() 56 it.join(DNS_TIMEOUT) 57 if it.isAlive(): 58 return DNS_TIMEOUT_VALUE 59 else: 60 if it.error: 61 raise it.error 62 return it.result 63
64 -def resolve_thread(name):
65 return with_timeout(gethostbyname, (name,))
66
67 -def gethostbyname(name):
68 try: 69 ip = socket.gethostbyname(name) 70 except socket.gaierror: 71 ip = "" 72 return ip
73 74 75 # C-ARES (http://c-ares.haxx.se/)
76 -def resolve_cares(name):
77 # create new c-ares channel 78 careschan = pycares.Channel(timeout=DNS_TIMEOUT, tries=1) 79 80 # if we don't get a response we return the default value 81 result = Resultholder() 82 result.value = DNS_TIMEOUT_VALUE 83 84 def setresult_cb(res, error): 85 # ignore error and just take first result ip (randomized anyway) 86 if res and res.addresses: 87 result.value = res.addresses[0]
88 89 # resolve with cb 90 careschan.gethostbyname(name, socket.AF_INET, setresult_cb) 91 92 # now do the actual work 93 readfds, writefds = careschan.getsock() 94 canreadfds, canwritefds, _ = select.select(readfds, writefds, [], 95 DNS_TIMEOUT) 96 for rfd in canreadfds: 97 careschan.process_fd(rfd, -1) 98 99 # if the query did not succeed, setresult was not called and we just 100 # return result destroy the channel first to not leak anything 101 careschan.destroy() 102 return result.value 103 104 # workaround until py3 nonlocal (for c-ares and gevent)
105 -class Resultholder:
106 pass
107 108 109 # gevent based resolver with timeout 110 """def resolve_gevent(name): 111 result = resolve_gevent_real(name) 112 # if it failed, do this a second time because of strange libevent behavior 113 # basically sometimes the Timeout fires immediately instead of after 114 # DNS_TIMEOUT 115 if result == DNS_TIMEOUT_VALUE: 116 result = resolve_gevent_real(name) 117 return result 118 119 def resolve_gevent_real(name): 120 result = DNS_TIMEOUT_VALUE 121 with gevent.Timeout(DNS_TIMEOUT, False): 122 try: 123 result = gevent.socket.gethostbyname(name) 124 except socket.gaierror: 125 pass 126 127 return result 128 """ 129 130 # choose resolver automatically
131 -def resolve(name):
132 if HAVE_CARES: 133 return resolve_cares(name) 134 #elif HAVE_GEVENT: 135 # return resolve_gevent(name) 136 else: 137 return resolve_thread(name)
138 139 # another alias 140 resolve_best = resolve 141