1
2
3
4
5 import os
6 import time
7 import shutil
8 import ntpath
9 import string
10 import tempfile
11 import xmlrpclib
12 import inspect
13 import threading
14 import multiprocessing
15 from datetime import datetime
16
17 from lib.cuckoo.common.exceptions import CuckooOperationalError
18 from lib.cuckoo.common.config import Config
19
20 try:
21 import chardet
22 HAVE_CHARDET = True
23 except ImportError:
24 HAVE_CHARDET = False
25
27 """Create directories.
28 @param root: root path.
29 @param folders: folders list to be created.
30 @raise CuckooOperationalError: if fails to create folder.
31 """
32 for folder in folders:
33 create_folder(root, folder)
34
36 """Create directory.
37 @param root: root path.
38 @param folder: folder name to be created.
39 @raise CuckooOperationalError: if fails to create folder.
40 """
41 folder_path = os.path.join(root, folder)
42 if folder and not os.path.isdir(folder_path):
43 try:
44 os.makedirs(folder_path)
45 except OSError:
46 raise CuckooOperationalError("Unable to create folder: %s" %
47 folder_path)
48
50 """Delete a folder and all its subdirectories.
51 @param folder: path to delete.
52 @raise CuckooOperationalError: if fails to delete folder.
53 """
54 if os.path.exists(folder):
55 try:
56 shutil.rmtree(folder)
57 except OSError:
58 raise CuckooOperationalError("Unable to delete folder: "
59 "{0}".format(folder))
60
61
62
63 PRINTABLE_CHARACTERS = \
64 string.letters + string.digits + string.punctuation + " \t\r\n"
65
67 """Escapes characters.
68 @param c: dirty char.
69 @return: sanitized char.
70 """
71 if c in PRINTABLE_CHARACTERS:
72 return c
73 else:
74 return "\\x%02x" % ord(c)
75
77 """ Test if a string is printable."""
78 for c in s:
79 if c not in PRINTABLE_CHARACTERS:
80 return False
81 return True
82
84 """Convert char to printable.
85 @param s: string.
86 @return: sanitized string.
87 """
88 if is_printable(s):
89 return s
90 return "".join(convert_char(c) for c in s)
91
93 """Parse a datatime string and returns a datetime in iso format.
94 @param timestamp: timestamp string
95 @return: ISO datetime
96 """
97 return datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S").isoformat()
98
100 """Cross-platform filename extraction from path.
101 @param path: file path.
102 @return: filename.
103 """
104 dirpath, filename = ntpath.split(path)
105 return filename if filename else ntpath.basename(dirpath)
106
108 """Store a temporary file.
109 @param filedata: content of the original file.
110 @param filename: name of the original file.
111 @param path: optional path for temp directory.
112 @return: path to the temporary file.
113 """
114 filename = get_filename_from_path(filename)
115
116
117 filename = filename[:100]
118
119 options = Config()
120
121 if path:
122 target_path = path
123 else:
124 tmp_path = options.cuckoo.get("tmppath", "/tmp")
125 target_path = os.path.join(tmp_path, "cuckoo-tmp")
126 if not os.path.exists(target_path):
127 os.mkdir(target_path)
128
129 tmp_dir = tempfile.mkdtemp(prefix="upload_", dir=target_path)
130 tmp_file_path = os.path.join(tmp_dir, filename)
131 with open(tmp_file_path, "wb") as tmp_file:
132
133 if hasattr(filedata, "read"):
134 chunk = filedata.read(1024)
135 while chunk:
136 tmp_file.write(chunk)
137 chunk = filedata.read(1024)
138 else:
139 tmp_file.write(filedata)
140
141 return tmp_file_path
142
144 """Timeout server for XMLRPC.
145 XMLRPC + timeout - still a bit ugly - but at least gets rid of setdefaulttimeout
146 inspired by http://stackoverflow.com/questions/372365/set-timeout-for-xmlrpclib-serverproxy
147 (although their stuff was messy, this is cleaner)
148 @see: http://stackoverflow.com/questions/372365/set-timeout-for-xmlrpclib-serverproxy
149 """
154
156 t = self._ServerProxy__transport
157 t.timeout = timeout
158
159 if hasattr(t, "_connection") and t._connection[1] and t._connection[1].sock:
160 t._connection[1].sock.settimeout(timeout)
161
164 self.timeout = kwargs.pop("timeout", None)
165 xmlrpclib.Transport.__init__(self, *args, **kwargs)
166
172
174 """Singleton.
175 @see: http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python
176 """
177 _instances = {}
178
183
185 """Formats time like a logger does, for the csv output
186 (e.g. "2013-01-25 13:21:44,590")
187 @param dt: datetime object
188 @return: time string
189 """
190 t = time.strftime("%Y-%m-%d %H:%M:%S", dt.timetuple())
191 s = "%s,%03d" % (t, dt.microsecond/1000)
192 return s
193
195 """Parse time string received from cuckoomon via netlog
196 @param s: time string
197 @return: datetime object
198 """
199 return datetime.strptime(s, "%Y-%m-%d %H:%M:%S,%f")
200
202 """Attempt to fix non uft-8 string into utf-8. It tries to guess input encoding,
203 if fail retry with a replace strategy (so undetectable chars will be escaped).
204 @see: fuller list of encodings at http://docs.python.org/library/codecs.html#standard-encodings
205 """
206
207 def brute_enc(s2):
208 """Trying to decode via simple brute forcing."""
209 encodings = ("ascii", "utf8", "latin1")
210 for enc in encodings:
211 try:
212 return unicode(s2, enc)
213 except UnicodeDecodeError:
214 pass
215 return None
216
217 def chardet_enc(s2):
218 """Guess encoding via chardet."""
219 enc = chardet.detect(s2)["encoding"]
220
221 try:
222 return unicode(s2, enc)
223 except UnicodeDecodeError:
224 pass
225 return None
226
227
228 if isinstance(s, unicode):
229 return s
230
231
232 result = brute_enc(s)
233
234
235 if not result and HAVE_CHARDET:
236 result = chardet_enc(s)
237
238
239
240 if not result:
241 result = unicode(s, errors="replace")
242
243 return result
244
246 """Cleanup utility function, strips some unwanted parts from values."""
247 v = str(v)
248 if v.startswith("\\??\\"):
249 v = v[4:]
250 return v
251
253 """Kind of awful but necessary sanitizing of filenames to
254 get rid of unicode problems."""
255 out = ""
256 for c in x:
257 if c in string.letters + string.digits + " _-.":
258 out += c
259 else:
260 out += "_"
261
262 return out
263
265 """Classlock decorator (created for database.Database).
266 Used to put a lock to avoid sqlite errors.
267 """
268 def inner(self, *args, **kwargs):
269 curframe = inspect.currentframe()
270 calframe = inspect.getouterframes(curframe, 2)
271
272 if calframe[1][1].endswith("database.py"):
273 return f(self, *args, **kwargs)
274
275 with self._lock:
276 return f(self, *args, **kwargs)
277
278 return inner
279
282 self.tlock = threading.Lock()
283 self.mlock = multiprocessing.Lock()
284
288 - def __exit__(self, type, value, traceback):
291