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 from datetime import datetime
13
14 from lib.cuckoo.common.exceptions import CuckooOperationalError
15 from lib.cuckoo.common.config import Config
16 from lib.cuckoo.common.constants import CUCKOO_ROOT
17
18 try:
19 import chardet
20 HAVE_CHARDET = True
21 except ImportError:
22 HAVE_CHARDET = False
23
25 """Create directories.
26 @param root: root path.
27 @param folders: folders list to be created.
28 @raise CuckooOperationalError: if fails to create folder.
29 """
30 for folder in folders:
31 if os.path.isdir(os.path.join(root, folder)):
32 continue
33 else:
34 create_folder(root, folder)
35
37 """Create directory.
38 @param root: root path.
39 @param folder: folder name to be created.
40 @raise CuckooOperationalError: if fails to create folder.
41 """
42 if not os.path.exists(os.path.join(root, folder)) and folder:
43 folder_path = os.path.join(root, folder)
44 if not os.path.isdir(folder_path):
45 try:
46 os.makedirs(folder_path)
47 except OSError:
48 raise CuckooOperationalError("Unable to create folder: %s" %
49 folder_path)
50
51
53 """Delete a folder and all its subdirectories.
54 @param folder: path to delete.
55 @raise CuckooOperationalError: if fails to delete folder.
56 """
57 if os.path.exists(folder):
58 try:
59 shutil.rmtree(folder)
60 except OSError:
61 raise CuckooOperationalError("Unable to delete folder: "
62 "{0}".format(folder))
63
64
65
66
67 PRINTABLE_CHARACTERS = string.letters + string.digits + string.punctuation + " \t\r\n"
68
69
71 """Escapes characters.
72 @param c: dirty char.
73 @return: sanitized char.
74 """
75 if c in PRINTABLE_CHARACTERS:
76 return c
77 else:
78 return "\\x%02x" % ord(c)
79
80
82 """ Test if a string is printable."""
83 for c in s:
84 if not c in PRINTABLE_CHARACTERS:
85 return False
86 return True
87
89 """Convert char to printable.
90 @param s: string.
91 @return: sanitized string.
92 """
93 if is_printable(s):
94 return s
95 return "".join(convert_char(c) for c in s)
96
98 """Parse a datatime string and returns a datetime in iso format.
99 @param timestamp: timestamp string
100 @return: ISO datetime
101 """
102 return datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S").isoformat()
103
105 """Cross-platform filename extraction from path.
106 @param path: file path.
107 @return: filename.
108 """
109 dirpath, filename = ntpath.split(path)
110 return filename if filename else ntpath.basename(dirpath)
111
113 """Store a temporary file.
114 @param filedata: content of the original file.
115 @param filename: name of the original file.
116 @return: path to the temporary file.
117 """
118 filename = get_filename_from_path(filename)
119
120
121 filename = filename[:100]
122
123 options = Config(os.path.join(CUCKOO_ROOT, "conf", "cuckoo.conf"))
124 tmppath = options.cuckoo.tmppath
125 targetpath = os.path.join(tmppath, "cuckoo-tmp")
126 if not os.path.exists(targetpath):
127 os.mkdir(targetpath)
128
129 tmp_dir = tempfile.mkdtemp(prefix="upload_", dir=targetpath)
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 = {}
182
184 """Formats time like a logger does, for the csv output
185 (e.g. "2013-01-25 13:21:44,590")
186 @param dt: datetime object
187 @return: time string
188 """
189 t = time.strftime("%Y-%m-%d %H:%M:%S", dt.timetuple())
190 s = "%s,%03d" % (t, dt.microsecond/1000)
191 return s
192
194 """Parse time string received from cuckoomon via netlog
195 @param s: time string
196 @return: datetime object
197 """
198 return datetime.strptime(s, "%Y-%m-%d %H:%M:%S,%f")
199
201 """Attempt to fix non uft-8 string into utf-8. It tries to guess input encoding,
202 if fail retry with a replace strategy (so undetectable chars will be escaped).
203 @see: fuller list of encodings at http://docs.python.org/library/codecs.html#standard-encodings
204 """
205
206 def brute_enc(s2):
207 """Trying to decode via simple brute forcing."""
208 encodings = ("ascii", "utf8", "latin1")
209 for enc in encodings:
210 try:
211 return unicode(s2, enc)
212 except UnicodeDecodeError:
213 pass
214 return None
215
216 def chardet_enc(s2):
217 """Guess encoding via chardet."""
218 enc = chardet.detect(s2)["encoding"]
219
220 try:
221 return unicode(s2, enc)
222 except UnicodeDecodeError:
223 pass
224 return None
225
226
227 if isinstance(s, unicode):
228 return s
229
230
231 result = brute_enc(s)
232
233
234 if (not result) and HAVE_CHARDET:
235 result = chardet_enc(s)
236
237
238
239 if not result:
240 result = unicode(s, errors="replace")
241
242 return result
243
245 """Cleanup utility function, strips some unwanted parts from values."""
246 v = str(v)
247 if v.startswith("\\??\\"):
248 v = v[4:]
249 return v
250
252 """Kind of awful but necessary sanitizing of filenames to
253 get rid of unicode problems."""
254 out = ""
255 for c in x:
256 if c in string.letters + string.digits + " _-.":
257 out += c
258 else:
259 out += "_"
260
261 return out
262