ft@0
|
1 |
#!/usr/bin/python
|
ft@0
|
2 |
|
ft@0
|
3 |
from fuse import Fuse
|
ft@0
|
4 |
import fuse
|
ft@0
|
5 |
|
ft@0
|
6 |
import ConfigParser
|
ft@0
|
7 |
|
ft@0
|
8 |
import sys
|
ft@0
|
9 |
|
ft@0
|
10 |
import logging
|
ft@0
|
11 |
import os
|
ft@0
|
12 |
import errno
|
ck@7
|
13 |
import time
|
ft@0
|
14 |
|
ft@11
|
15 |
from importlib import import_module
|
ft@11
|
16 |
|
ft@11
|
17 |
|
ft@0
|
18 |
import subprocess
|
ft@0
|
19 |
|
ck@5
|
20 |
import urllib3
|
ft@8
|
21 |
import netifaces
|
ft@8
|
22 |
import netaddr
|
ft@15
|
23 |
import hashlib
|
ck@1
|
24 |
|
ck@1
|
25 |
|
ft@11
|
26 |
sys.stderr = open('/var/log/osecfs_error.log', 'a+')
|
ft@11
|
27 |
|
ft@11
|
28 |
|
ft@11
|
29 |
MINOPTS = { "Main" : ["Logfile", "LogLevel", "Mountpoint", "Rootpath", "ScannerPath", "ScannerModuleName", "ScannerClassName", "ScannerConfig", "ReadOnly"]}
|
ft@0
|
30 |
|
ft@0
|
31 |
CONFIG_NOT_READABLE = "Configfile is not readable"
|
ft@0
|
32 |
CONFIG_WRONG = "Something is wrong with the config"
|
ft@0
|
33 |
CONFIG_MISSING = "Section: \"%s\" Option: \"%s\" in configfile is missing"
|
ft@11
|
34 |
SCAN_WRONG_RETURN_VALUE = "The return Value of the malware scanner is wrong. Has to be an dictionary"
|
ft@11
|
35 |
SCAN_RETURN_VALUE_KEY_MISSING = "The dictionary has to include key \"infected\" (True, False) and \"virusname\" (String)"
|
ft@11
|
36 |
VIRUS_FOUND = "Virus found. Access denied"
|
ft@11
|
37 |
NOTIFICATION_CRITICAL = "critical"
|
ft@11
|
38 |
NOTIFICATION_INFO = "info"
|
ft@0
|
39 |
LOG = None
|
ft@11
|
40 |
MalwareScanner = None
|
ft@13
|
41 |
STATUS_CODE_OK = 200
|
ft@0
|
42 |
|
ft@0
|
43 |
SYSTEM_FILE_COMMAND = "file"
|
ck@7
|
44 |
httpPool = urllib3.PoolManager(num_pools = 1, timeout = 3)
|
ft@0
|
45 |
|
ft@0
|
46 |
def checkMinimumOptions (config):
|
ft@0
|
47 |
for section, options in MINOPTS.iteritems ():
|
ft@0
|
48 |
for option in options:
|
ft@0
|
49 |
if (config.has_option(section, option) == False):
|
ft@0
|
50 |
print (CONFIG_MISSING % (section, option))
|
ft@0
|
51 |
exit (129)
|
ft@0
|
52 |
|
ft@0
|
53 |
def printUsage ():
|
ft@0
|
54 |
print ("Usage:")
|
ft@3
|
55 |
print ("%s configfile mountpath ro/rw" % (sys.argv[0]))
|
ft@0
|
56 |
exit (128)
|
ft@0
|
57 |
|
ft@0
|
58 |
def loadConfig ():
|
ft@0
|
59 |
print ("load config")
|
ft@0
|
60 |
|
ft@3
|
61 |
if (len (sys.argv) < 4):
|
ft@0
|
62 |
printUsage ()
|
ft@0
|
63 |
|
ft@0
|
64 |
configfile = sys.argv[1]
|
ft@0
|
65 |
config = ConfigParser.SafeConfigParser ()
|
ft@0
|
66 |
|
ft@0
|
67 |
if ((os.path.exists (configfile) == False) or (os.path.isfile (configfile) == False) or (os.access (configfile, os.R_OK) == False)):
|
ft@0
|
68 |
print (CONFIG_NOT_READABLE)
|
ft@0
|
69 |
printUsage ()
|
ft@0
|
70 |
|
ft@0
|
71 |
try:
|
ft@0
|
72 |
config.read (sys.argv[1])
|
ft@0
|
73 |
except Exception, e:
|
ft@0
|
74 |
print (CONFIG_WRONG)
|
ft@0
|
75 |
print ("Error: %s" % (e))
|
ft@0
|
76 |
|
ft@3
|
77 |
|
ft@3
|
78 |
config.set("Main", "Mountpoint", sys.argv[2])
|
ft@3
|
79 |
if (sys.argv[3] == "rw"):
|
ft@3
|
80 |
config.set("Main", "ReadOnly", "false")
|
ft@3
|
81 |
else:
|
ft@3
|
82 |
config.set("Main", "ReadOnly", "true")
|
ft@3
|
83 |
|
ft@0
|
84 |
checkMinimumOptions (config)
|
ft@0
|
85 |
|
ft@0
|
86 |
return config
|
ft@0
|
87 |
|
ft@0
|
88 |
def initLog (config):
|
ft@0
|
89 |
print ("init log")
|
ft@0
|
90 |
|
ft@0
|
91 |
global LOG
|
ft@0
|
92 |
logfile = config.get("Main", "Logfile")
|
ft@11
|
93 |
|
ft@11
|
94 |
numeric_level = getattr(logging, config.get("Main", "LogLevel").upper(), None)
|
ft@11
|
95 |
if not isinstance(numeric_level, int):
|
ft@11
|
96 |
raise ValueError('Invalid log level: %s' % loglevel)
|
ft@0
|
97 |
|
ft@0
|
98 |
# ToDo move log level and maybe other things to config file
|
ft@0
|
99 |
logging.basicConfig(
|
ft@11
|
100 |
level = numeric_level,
|
ft@0
|
101 |
format = "%(asctime)s %(name)-12s %(funcName)-15s %(levelname)-8s %(message)s",
|
ft@0
|
102 |
datefmt = "%Y-%m-%d %H:%M:%S",
|
ft@0
|
103 |
filename = logfile,
|
ft@0
|
104 |
filemode = "a+",
|
ft@0
|
105 |
)
|
ft@0
|
106 |
LOG = logging.getLogger("fuse_main")
|
ft@0
|
107 |
|
ft@0
|
108 |
|
ft@0
|
109 |
def fixPath (path):
|
ft@0
|
110 |
return ".%s" % (path)
|
ft@0
|
111 |
|
ft@0
|
112 |
def rootPath (rootpath, path):
|
ft@0
|
113 |
return "%s%s" % (rootpath, path)
|
ft@0
|
114 |
|
ft@0
|
115 |
def flag2mode (flags):
|
ft@0
|
116 |
md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
|
ft@0
|
117 |
m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
|
ft@0
|
118 |
|
ft@14
|
119 |
# windows sets append even if it would overwrite the whole file (seek 0)
|
ft@14
|
120 |
# so ignore append option
|
ft@14
|
121 |
#if flags | os.O_APPEND:
|
ft@14
|
122 |
# m = m.replace('w', 'a', 1)
|
ft@0
|
123 |
|
ft@0
|
124 |
return m
|
ft@0
|
125 |
|
ft@11
|
126 |
def scanFile (path, fileobject):
|
ft@11
|
127 |
LOG.debug ("Scan File \"%s\" with malware Scanner" %(path,) )
|
ft@11
|
128 |
return MalwareScanner.scanFile (path, fileobject)
|
ck@7
|
129 |
|
ck@2
|
130 |
|
ck@2
|
131 |
def scanFileClamAV (path):
|
ft@0
|
132 |
infected = False
|
ft@0
|
133 |
|
ft@0
|
134 |
LOG.debug ("Scan File: %s" % (path))
|
ft@0
|
135 |
|
ck@2
|
136 |
result = pyclamav.scanfile (path)
|
ft@0
|
137 |
LOG.debug ("Result of file \"%s\": %s" % (path, result))
|
ck@2
|
138 |
if (result[0] != 0):
|
ft@0
|
139 |
infected = True
|
ft@0
|
140 |
|
ft@0
|
141 |
if (infected == True):
|
ck@2
|
142 |
LOG.error ("Virus found, deny Access %s" % (result,))
|
ft@0
|
143 |
|
ft@0
|
144 |
return infected
|
ft@0
|
145 |
|
ft@0
|
146 |
def whitelistFile (path):
|
ft@0
|
147 |
whitelisted = False;
|
ft@0
|
148 |
|
ft@0
|
149 |
LOG.debug ("Execute \"%s\" command on \"%s\"" %(SYSTEM_FILE_COMMAND, path))
|
ft@0
|
150 |
|
ft@0
|
151 |
result = None
|
ft@0
|
152 |
try:
|
ft@0
|
153 |
result = subprocess.check_output ([SYSTEM_FILE_COMMAND, path]);
|
ft@0
|
154 |
# ToDo replace with real whitelist
|
ft@0
|
155 |
whitelisted = True
|
ft@0
|
156 |
except Exception as e:
|
ft@0
|
157 |
LOG.error ("Call returns with an error!")
|
ft@0
|
158 |
LOG.error (e)
|
ft@0
|
159 |
|
ft@0
|
160 |
LOG.debug ("Type: %s" %(result))
|
ft@0
|
161 |
|
ft@0
|
162 |
return whitelisted
|
ft@0
|
163 |
|
ft@15
|
164 |
def sendDataToRest (urlpath, data):
|
ft@8
|
165 |
netifaces.ifaddresses("eth0")[2][0]["addr"]
|
ft@8
|
166 |
|
ft@8
|
167 |
# Get first address in network (0 = network ip -> 192.168.0.0)
|
ft@8
|
168 |
remote_ip = netaddr.IPNetwork("%s/%s" %(netifaces.ifaddresses("eth0")[2][0]["addr"], netifaces.ifaddresses("eth0")[2][0]["netmask"]))[1]
|
ft@8
|
169 |
|
ft@15
|
170 |
url = ("http://%s:8090//%s" %(remote_ip, urlpath))
|
ft@15
|
171 |
|
ft@15
|
172 |
LOG.debug ("Send data to \"%s\"" %(url, ))
|
ft@15
|
173 |
LOG.debug ("Data: %s" %(data, ))
|
ft@8
|
174 |
|
ft@8
|
175 |
try:
|
ft@15
|
176 |
response = httpPool.request_encode_body("POST", url, fields=data, retries=0)
|
ft@16
|
177 |
except Exception, e:
|
ft@8
|
178 |
LOG.error("Remote host not reachable")
|
ft@16
|
179 |
LOG.error ("Exception: %s" %(e,))
|
ft@8
|
180 |
return
|
ft@8
|
181 |
|
ft@8
|
182 |
if response.status == STATUS_CODE_OK:
|
ft@15
|
183 |
LOG.info("Data sent successfully to rest server")
|
ft@15
|
184 |
return True
|
ft@8
|
185 |
else:
|
ft@8
|
186 |
LOG.error("Server returned errorcode: %s" %(response.status,))
|
ft@15
|
187 |
return False
|
ft@15
|
188 |
|
ft@15
|
189 |
|
ft@15
|
190 |
def sendNotification (type, message):
|
ft@19
|
191 |
data = {"msgtype" : type, "text" : message}
|
ft@20
|
192 |
|
ft@20
|
193 |
if (type == "information"):
|
ft@20
|
194 |
sendDataToRest ("message", data)
|
ft@20
|
195 |
else:
|
ft@20
|
196 |
sendDataToRest ("notification", data)
|
ft@8
|
197 |
|
ft@9
|
198 |
def sendReadOnlyNotification():
|
ft@9
|
199 |
sendNotification("critical", "Filesystem is in read only mode. If you want to export files please initialize an encrypted filesystem.")
|
ft@15
|
200 |
|
ft@15
|
201 |
def sendLogNotPossibleNotification():
|
ft@20
|
202 |
sendNotification("critical", "Send log entry to opensecurity rest server failed.")
|
ft@15
|
203 |
|
ft@15
|
204 |
def sendFileLog(filename, filesize, filehash, hashtype):
|
ft@16
|
205 |
data = {"filename" : filename, "filesize" : "%s" %(filesize,), "filehash" : filehash, "hashtype" : hashtype}
|
ft@15
|
206 |
retval = sendDataToRest ("log", data)
|
ft@15
|
207 |
if (retval == False):
|
ft@15
|
208 |
sendLogNotPossibleNotification()
|
ft@15
|
209 |
|
ft@15
|
210 |
def calcMD5 (path, block_size=256*128, hr=True):
|
ft@15
|
211 |
md5 = hashlib.md5()
|
ft@15
|
212 |
with open(path,'rb') as f:
|
ft@15
|
213 |
for chunk in iter(lambda: f.read(block_size), b''):
|
ft@15
|
214 |
md5.update(chunk)
|
ft@15
|
215 |
if hr:
|
ft@15
|
216 |
return md5.hexdigest()
|
ft@15
|
217 |
return md5.digest()
|
ft@9
|
218 |
|
ft@0
|
219 |
class OsecFS (Fuse):
|
ft@0
|
220 |
|
ft@0
|
221 |
__rootpath = None
|
ft@0
|
222 |
|
ft@0
|
223 |
# default fuse init
|
ft@0
|
224 |
def __init__(self, rootpath, *args, **kw):
|
ft@0
|
225 |
self.__rootpath = rootpath
|
ft@0
|
226 |
Fuse.__init__ (self, *args, **kw)
|
ft@0
|
227 |
LOG.debug ("Init complete.")
|
ft@9
|
228 |
sendNotification("information", "Filesystem successfully mounted.")
|
ft@0
|
229 |
|
ft@0
|
230 |
# defines that our working directory will be the __rootpath
|
ft@0
|
231 |
def fsinit(self):
|
ft@0
|
232 |
os.chdir (self.__rootpath)
|
ft@0
|
233 |
|
ft@0
|
234 |
def getattr(self, path):
|
ft@0
|
235 |
LOG.debug ("*** getattr (%s)" % (fixPath (path)))
|
ft@0
|
236 |
return os.lstat (fixPath (path));
|
ft@0
|
237 |
|
ft@0
|
238 |
def getdir(self, path):
|
ft@0
|
239 |
LOG.debug ("*** getdir (%s)" % (path));
|
ft@0
|
240 |
return os.listdir (fixPath (path))
|
ft@0
|
241 |
|
ft@0
|
242 |
def readdir(self, path, offset):
|
ft@0
|
243 |
LOG.debug ("*** readdir (%s %s)" % (path, offset));
|
ft@0
|
244 |
for e in os.listdir (fixPath (path)):
|
ft@0
|
245 |
yield fuse.Direntry(e)
|
ft@0
|
246 |
|
ft@0
|
247 |
def chmod (self, path, mode):
|
ft@0
|
248 |
LOG.debug ("*** chmod %s %s" % (path, oct(mode)))
|
ft@3
|
249 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
250 |
sendReadOnlyNotification()
|
ft@3
|
251 |
return -errno.EACCES
|
ft@0
|
252 |
os.chmod (fixPath (path), mode)
|
ft@0
|
253 |
|
ft@0
|
254 |
def chown (self, path, uid, gid):
|
ft@0
|
255 |
LOG.debug ("*** chown %s %s %s" % (path, uid, gid))
|
ft@3
|
256 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
257 |
sendReadOnlyNotification()
|
ft@3
|
258 |
return -errno.EACCES
|
ft@0
|
259 |
os.chown (fixPath (path), uid, gid)
|
ft@0
|
260 |
|
ft@0
|
261 |
def link (self, targetPath, linkPath):
|
ft@0
|
262 |
LOG.debug ("*** link %s %s" % (targetPath, linkPath))
|
ft@3
|
263 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
264 |
sendReadOnlyNotification()
|
ft@3
|
265 |
return -errno.EACCES
|
ft@0
|
266 |
os.link (fixPath (targetPath), fixPath (linkPath))
|
ft@0
|
267 |
|
ft@0
|
268 |
def mkdir (self, path, mode):
|
ft@0
|
269 |
LOG.debug ("*** mkdir %s %s" % (path, oct(mode)))
|
ft@3
|
270 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
271 |
sendReadOnlyNotification()
|
ft@3
|
272 |
return -errno.EACCES
|
ft@0
|
273 |
os.mkdir (fixPath (path), mode)
|
ft@0
|
274 |
|
ft@0
|
275 |
def mknod (self, path, mode, dev):
|
ft@0
|
276 |
LOG.debug ("*** mknod %s %s %s" % (path, oct (mode), dev))
|
ft@3
|
277 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
278 |
sendReadOnlyNotification()
|
ft@3
|
279 |
return -errno.EACCES
|
ft@0
|
280 |
os.mknod (fixPath (path), mode, dev)
|
ft@0
|
281 |
|
ft@0
|
282 |
# to implement virus scan
|
ft@0
|
283 |
def open (self, path, flags):
|
ft@0
|
284 |
LOG.debug ("*** open %s %s" % (path, oct (flags)))
|
ft@0
|
285 |
self.file = os.fdopen (os.open (fixPath (path), flags), flag2mode (flags))
|
ft@15
|
286 |
self.written = False
|
ft@0
|
287 |
self.fd = self.file.fileno ()
|
ft@11
|
288 |
|
ft@11
|
289 |
LOG.debug(self.__rootpath)
|
ft@11
|
290 |
LOG.debug(path)
|
ft@11
|
291 |
|
ft@11
|
292 |
retval = scanFile (rootPath(self.__rootpath, path), self.file)
|
ft@11
|
293 |
|
ft@11
|
294 |
#if type(retval) is not dict:
|
ft@11
|
295 |
if (isinstance(retval, dict) == False):
|
ft@11
|
296 |
LOG.error(SCAN_WRONG_RETURN_VALUE)
|
ft@0
|
297 |
self.file.close ()
|
ft@11
|
298 |
return -errno.EACCES
|
ft@11
|
299 |
|
ft@11
|
300 |
if ((retval.has_key("infected") == False) or (retval.has_key("virusname") == False)):
|
ft@11
|
301 |
LOG.error(SCAN_RETURN_VALUE_KEY_MISSING)
|
ft@11
|
302 |
self.file.close ()
|
ft@11
|
303 |
return -errno.EACCES
|
ft@11
|
304 |
|
ft@11
|
305 |
|
ft@11
|
306 |
if (retval.get("infected") == True):
|
ft@11
|
307 |
self.file.close ()
|
ft@11
|
308 |
sendNotification(NOTIFICATION_CRITICAL, "%s\nFile: %s\nVirus: %s" %(VIRUS_FOUND, path, retval.get("virusname")))
|
ft@11
|
309 |
LOG.error("%s" %(VIRUS_FOUND,))
|
ft@11
|
310 |
LOG.error("Virus: %s" %(retval.get("virusname"),))
|
ft@0
|
311 |
return -errno.EACCES
|
ft@0
|
312 |
|
ft@0
|
313 |
whitelisted = whitelistFile (rootPath(self.__rootpath, path))
|
ft@0
|
314 |
if (whitelisted == False):
|
ft@0
|
315 |
self.file.close ()
|
ft@11
|
316 |
sendNotification(NOTIFICATION_CRITICAL, "File not in whitelist. Access denied.")
|
ft@0
|
317 |
return -errno.EACCES
|
ft@0
|
318 |
|
ft@0
|
319 |
def read (self, path, length, offset):
|
ft@0
|
320 |
LOG.debug ("*** read %s %s %s" % (path, length, offset))
|
ft@0
|
321 |
self.file.seek (offset)
|
ft@0
|
322 |
return self.file.read (length)
|
ft@0
|
323 |
|
ft@0
|
324 |
def readlink (self, path):
|
ft@0
|
325 |
LOG.debug ("*** readlink %s" % (path))
|
ft@0
|
326 |
return os.readlink (fixPath (path))
|
ft@0
|
327 |
|
ft@0
|
328 |
def release (self, path, flags):
|
ft@0
|
329 |
LOG.debug ("*** release %s %s" % (path, oct (flags)))
|
ft@18
|
330 |
self.file.flush()
|
ft@18
|
331 |
os.fsync(self.file.fileno())
|
ft@0
|
332 |
self.file.close ()
|
ft@15
|
333 |
|
ft@15
|
334 |
if (self.written == True):
|
ft@15
|
335 |
hashsum = calcMD5(fixPath(path))
|
ft@15
|
336 |
filesize = os.path.getsize(fixPath(path))
|
ft@15
|
337 |
sendFileLog(path, filesize, hashsum, "md5")
|
ft@15
|
338 |
|
ft@0
|
339 |
|
ft@0
|
340 |
def rename (self, oldPath, newPath):
|
ft@3
|
341 |
LOG.debug ("*** rename %s %s %s" % (oldPath, newPath, config.get("Main", "ReadOnly")))
|
ft@3
|
342 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
343 |
sendReadOnlyNotification()
|
ft@3
|
344 |
return -errno.EACCES
|
ft@0
|
345 |
os.rename (fixPath (oldPath), fixPath (newPath))
|
ft@0
|
346 |
|
ft@0
|
347 |
def rmdir (self, path):
|
ft@3
|
348 |
LOG.debug ("*** rmdir %s %s" % (path, config.get("Main", "ReadOnly")))
|
ft@3
|
349 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
350 |
sendReadOnlyNotification()
|
ft@3
|
351 |
return -errno.EACCES
|
ft@0
|
352 |
os.rmdir (fixPath (path))
|
ft@0
|
353 |
|
ft@0
|
354 |
def statfs (self):
|
ft@0
|
355 |
LOG.debug ("*** statfs")
|
ft@0
|
356 |
return os.statvfs(".")
|
ft@0
|
357 |
|
ft@0
|
358 |
def symlink (self, targetPath, linkPath):
|
ft@3
|
359 |
LOG.debug ("*** symlink %s %s %s" % (targetPath, linkPath, config.get("Main", "ReadOnly")))
|
ft@3
|
360 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
361 |
sendReadOnlyNotification()
|
ft@3
|
362 |
return -errno.EACCES
|
ft@0
|
363 |
os.symlink (fixPath (targetPath), fixPath (linkPath))
|
ft@0
|
364 |
|
ft@0
|
365 |
def truncate (self, path, length):
|
ft@3
|
366 |
LOG.debug ("*** truncate %s %s %s" % (path, length, config.get("Main", "ReadOnly")))
|
ft@3
|
367 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
368 |
sendReadOnlyNotification()
|
ft@3
|
369 |
return -errno.EACCES
|
ft@14
|
370 |
f = open (fixPath (path), "w+")
|
ft@0
|
371 |
f.truncate (length)
|
ft@0
|
372 |
f.close ()
|
ft@0
|
373 |
|
ft@0
|
374 |
def unlink (self, path):
|
ft@3
|
375 |
LOG.debug ("*** unlink %s %s" % (path, config.get("Main", "ReadOnly")))
|
ft@3
|
376 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
377 |
sendReadOnlyNotification()
|
ft@3
|
378 |
return -errno.EACCES
|
ft@0
|
379 |
os.unlink (fixPath (path))
|
ft@0
|
380 |
|
ft@0
|
381 |
def utime (self, path, times):
|
ft@0
|
382 |
LOG.debug ("*** utime %s %s" % (path, times))
|
ft@0
|
383 |
os.utime (fixPath (path), times)
|
ft@0
|
384 |
|
ft@0
|
385 |
def write (self, path, buf, offset):
|
ft@15
|
386 |
#LOG.debug ("*** write %s %s %s %s" % (path, buf, offset, config.get("Main", "ReadOnly")))
|
ft@15
|
387 |
LOG.debug ("*** write %s %s %s %s" % (path, "filecontent", offset, config.get("Main", "ReadOnly")))
|
ft@3
|
388 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@3
|
389 |
self.file.close()
|
ft@9
|
390 |
sendReadOnlyNotification()
|
ft@3
|
391 |
return -errno.EACCES
|
ft@0
|
392 |
self.file.seek (offset)
|
ft@0
|
393 |
self.file.write (buf)
|
ft@15
|
394 |
self.written = True
|
ft@0
|
395 |
return len (buf)
|
ft@0
|
396 |
|
ft@0
|
397 |
def access (self, path, mode):
|
ft@0
|
398 |
LOG.debug ("*** access %s %s" % (path, oct (mode)))
|
ft@0
|
399 |
if not os.access (fixPath (path), mode):
|
ft@0
|
400 |
return -errno.EACCES
|
ft@0
|
401 |
|
ft@0
|
402 |
def create (self, path, flags, mode):
|
ft@3
|
403 |
LOG.debug ("*** create %s %s %s %s %s" % (fixPath (path), oct (flags), oct (mode), flag2mode (flags), config.get("Main", "ReadOnly")))
|
ft@3
|
404 |
if (config.get("Main", "ReadOnly") == "true"):
|
ft@9
|
405 |
sendReadOnlyNotification()
|
ft@3
|
406 |
return -errno.EACCES
|
ft@15
|
407 |
|
ft@15
|
408 |
self.file = os.fdopen (os.open (fixPath (path), flags), flag2mode(flags))
|
ft@15
|
409 |
self.written = True
|
ft@0
|
410 |
self.fd = self.file.fileno ()
|
ft@0
|
411 |
|
ft@0
|
412 |
|
ft@0
|
413 |
if __name__ == "__main__":
|
ft@0
|
414 |
# Set api version
|
ft@0
|
415 |
fuse.fuse_python_api = (0, 2)
|
ft@0
|
416 |
fuse.feature_assert ('stateful_files', 'has_init')
|
ft@0
|
417 |
|
ft@0
|
418 |
config = loadConfig ()
|
ft@0
|
419 |
initLog (config)
|
ft@8
|
420 |
|
ft@8
|
421 |
#sendNotification("Info", "OsecFS started")
|
ft@11
|
422 |
|
ft@11
|
423 |
# Import the Malware Scanner
|
ft@11
|
424 |
sys.path.append(config.get("Main", "ScannerPath"))
|
ft@11
|
425 |
|
ft@11
|
426 |
MalwareModule = import_module(config.get("Main", "ScannerModuleName"))
|
ft@11
|
427 |
MalwareClass = getattr(MalwareModule, config.get("Main", "ScannerClassName"))
|
ft@11
|
428 |
|
ft@11
|
429 |
MalwareScanner = MalwareClass (config.get("Main", "ScannerConfig"));
|
ck@7
|
430 |
|
ft@0
|
431 |
osecfs = OsecFS (config.get ("Main", "Rootpath"))
|
ft@0
|
432 |
osecfs.flags = 0
|
ft@0
|
433 |
osecfs.multithreaded = 0
|
ft@0
|
434 |
|
ft@0
|
435 |
fuse_args = [sys.argv[0], config.get ("Main", "Mountpoint")];
|
ft@0
|
436 |
osecfs.main (fuse_args)
|