def get_file_info(system, path): fullpath = get_fullpath(system, path) if fullpath == IO_ERROR: return IO_ERROR if system.startswith('/'): # local or sub if can_read(system, path): result = {} # TODO platform-specific stats = os.stat(fullpath) stm = stats.st_mode result['type'] = get_file_type_char(stat.S_IFMT(stm)) result['permissions'] = '%o' % (stat.S_IMODE(stm)) result['UID'] = stat.ST_UID result['GID'] = stat.ST_GID result['ATIME'] = stat.ST_ATIME result['MTIME'] = stat.ST_MTIME result['CTIME'] = stat.ST_CTIME # actually mtime on UNIX, TODO return result else: log.err('Cannot get stats of \'%s\'.' % (fullpath)) return IO_ERROR else: # SSH/FTP/TFTP/HTTP # NOT IMPLEMENTED return IO_ERROR
def read_file(system, path, usedb=False): fullpath = get_fullpath(system, path) if fullpath == IO_ERROR: return IO_ERROR if not can_read(system, path): log.err('Cannot read \'%s\'' % (fullpath)) return IO_ERROR if system.startswith('/'): # local or sub try: with open(fullpath, 'r', encoding='utf-8') as f: result = f.read() except: # a binary file? with open(fullpath, 'rb') as f: result = f.read() if usedb == True or usedb == DBFILE_NOCONTENT: fileinfo = get_file_info(system, path) if fileinfo == IO_ERROR: return IO_ERROR # cannot access file info - something is weird add = db['analysis'].add_file(system, path, fileinfo['type'], fileinfo['permissions'], fileinfo['UID'], fileinfo['GID'], result if usedb else None, fileinfo['ATIME'], fileinfo['MTIME'], fileinfo['CTIME']) if not add: log.err('Database query failed.') return IO_ERROR return result else: # SSH/FTP/TFTP/HTTP # NOT IMPLEMENTED return IO_ERROR
def executemany(self, command, parameters): try: self.connection.executemany(command, parameters) self.commit() return True except Exception as e: log.err(str(e) + ' for ' + command) return DB_ERROR
def executemany(self, command, parameters, ignoreerrors=False): try: self.connection.executemany(command, parameters) self.commit() return True except Exception as e: if not ignoreerrors: log.err(str(e) + ' for ' + command) return DB_ERROR
def execute(self, command, parameters=None, commit=True): try: if parameters is None: self.cursor.execute(command) else: self.cursor.execute(command, parameters) if commit: self.commit() return self.cursor.fetchall() except Exception as e: log.err(str(e) + ' -- ' + command) return DB_ERROR
def mkdir(system, path): fullpath = get_fullpath(system, path) if can_read(system, path): typ = get_file_info(system, path)['type'] if typ != 'd': log.err('This file already exists (and is not a directory).') return if system.startswith('/'): # local or sub os.mkdir(fullpath) else: #TODO NOT IMPLEMENTED pass
def search(self, keys, parent=False, silent=True, boolean=False): i = 0 if type(keys) is bytes: keys = keys.decode('utf-8') if type(keys) is str: keys = [x for x in keys.split(' ') if len(x) > 0] branch = self.kb parentbranch = None # search branch one key at a time for i in range(0, len(keys)): parentbranch = branch # working with dict? is the key present? if type(branch) == dict and keys[i] in branch: branch = branch[keys[i]] # list or tuple? is key a number? is the key there? elif (type(branch) == list or type(branch) == tuple ) and keys[i].isdigit() and int(keys[i]) < len(branch): branch = branch[int(keys[i])] # dealing with last key and the branch is only a string? elif i == len(keys) - 1 and type(branch) == str: tmpbranch = [x for x in branch.splitlines() if keys[i] in x] if len(tmpbranch) == 0: if not silent: log.err('Cannot find key \'%s\'.' % keys[i]) if boolean: return False # key not found i -= 1 break if boolean: return True else: if parent: return (parentbranch, i) else: return (tmpbranch, i) # weird branch type else: if not silent: log.err('Cannot find key \'%s\'.' % keys[i]) if boolean: return False # key not found i -= 1 break if boolean: return True # key found else: if parent: return (parentbranch, i ) # return parent node of last branch found else: return (branch, i) # return last branch found
def search(self, keys, parent=False, silent=True, boolean=False): i = 0 if type(keys) is bytes: keys = keys.decode('utf-8') if type(keys) is str: keys = [x for x in keys.split(' ') if len(x)>0] branch = self.kb parentbranch = None # search branch one key at a time for i in range(0, len(keys)): parentbranch = branch # working with dict? is the key present? if type(branch) == dict and keys[i] in branch: branch = branch[keys[i]] # list or tuple? is key a number? is the key there? elif (type(branch) == list or type(branch) == tuple) and keys[i].isdigit() and int(keys[i])<len(branch): branch = branch[int(keys[i])] # dealing with last key and the branch is only a string? elif i == len(keys)-1 and type(branch) == str: tmpbranch = [x for x in branch.splitlines() if keys[i] in x] if len(tmpbranch) == 0: if not silent: log.err('Cannot find key \'%s\'.' % keys[i]) if boolean: return False # key not found i -= 1 break if boolean: return True else: if parent: return (parentbranch, i) else: return (tmpbranch, i) # weird branch type else: if not silent: log.err('Cannot find key \'%s\'.' % keys[i]) if boolean: return False # key not found i -= 1 break if boolean: return True # key found else: if parent: return (parentbranch, i) # return parent node of last branch found else: return (branch, i) # return last branch found
def add(self, key, data): # split into words if given as a string if type(key) == str: key = key.split(' ') # index of the deepest known keyword (-1 = nowhere) existindex = -1 if not self.exists(key[:-1]): # parent does not exist - create dictionaries self.lock.acquire() for i in range(0, len(key[:-1])): if self.exists(key[:len(key) - i - 1]): existindex = i break # existindex should be correct here if existindex == -1: # not found anything => kb itself branch = self.kb existindex = 0 # noted, now create from first... else: # work with the existing branch branch = self.find(key[:existindex]) # create dictionaries except last one (that will be added as a key) for x in key[existindex:-1]: branch[x] = {} branch = branch[x] self.lock.release() # now the tree should be ok for addition, try again self.add(key, data) return # tree is ok, add it there self.lock.acquire() branch = self.find(key[:-1]) # add the last key if type(branch) == dict: branch[key[-1]] = data elif type(branch) == list: branch += data #TODO correct? elif type(branch) == str: branch += data #TODO correct? elif type(branch) == tuple: log.err('You cannot add data into an existing tuple.') else: log.err( 'Attempt to add structure into one of unsupported type: %s.' % type(branch)) self.lock.release()
def add(self, key, data): # split into words if given as a string if type(key) == str: key = key.split(' ') # index of the deepest known keyword (-1 = nowhere) existindex = -1 if not self.exists(key[:-1]): # parent does not exist - create dictionaries self.lock.acquire() for i in range(0, len(key[:-1])): if self.exists(key[:len(key)-i-1]): existindex = i break # existindex should be correct here if existindex == -1: # not found anything => kb itself branch = self.kb existindex = 0 # noted, now create from first... else: # work with the existing branch branch = self.find(key[:existindex]) # create dictionaries except last one (that will be added as a key) for x in key[existindex:-1]: branch[x] = {} branch = branch[x] self.lock.release() # now the tree should be ok for addition, try again self.add(key, data) return # tree is ok, add it there self.lock.acquire() branch = self.find(key[:-1]) # add the last key if type(branch) == dict: branch[key[-1]] = data elif type(branch) == list: branch += data #TODO correct? elif type(branch) == str: branch += data #TODO correct? elif type(branch) == tuple: log.err('You cannot add data into an existing tuple.') else: log.err('Attempt to add structure into one of unsupported type: %s.' % type(branch)) self.lock.release()
def execute(self, command, parameters=None, commit=True, ignoreerrors=False): try: #print('$', command) if parameters is None: self.cursor.execute(command) else: self.cursor.execute(command, parameters) if commit: self.commit() return self.cursor.fetchall() except Exception as e: if not ignoreerrors: log.err(str(e) + ' -- ' + command) return DB_ERROR
def main(): global_parameters['UUID'] = get_local_uuid() lib.active_session = db['analysis'].get_last_session() db['analysis'].create_session(lib.active_session) log.info('Currently working with session #%d.' % lib.active_session) # check if already admin if is_admin(): log.ok('Administrator privileges already granted on \'%s\'.' % (global_parameters['ACTIVEROOT']), dbnote=DBNOTE_UNIQUE) # if input from file, load commands into queue if args.input_file is not None: if os.access(args.input_file[0], os.R_OK): with open(args.input_file[0], 'r') as f: lib.commands = f.read().splitlines() lib.from_input_file = True else: log.err('Input file cannot be read!') # run all input commands while len(lib.commands) > 0: c = lib.commands[0] del lib.commands[0] if lib.from_input_file: log.prompt() # print prompt log.attachline(c) # print command execute_command(c) # run the command lib.from_input_file = False # main loop while True: # input from stdin log.prompt() if lib.python_version[0] == '2': func = raw_input elif lib.python_version[0] == '3': func = input else: log.err('Undefined python version (%s).' % lib.python_version) break # add command into queue #lib.commands.append(func()) execute_command(func())
def write_file(system, path, content, lf=True, utf8=False): fullpath = get_fullpath(system, path) if fullpath == IO_ERROR: return IO_ERROR if not can_write(system, path) and not can_create(system, path): log.err('Cannot write \'%s\'' % (fullpath)) return IO_ERROR if system.startswith('/'): # local or sub # LF? UTF-8? args = {} if lf: args['newline'] = '' if utf8: args['encoding'] = 'utf-8' try: # write file with open(fullpath, 'w', **args) as f: f.write(content) except UnicodeEncodeError: # weird char? try utf8 args['encoding'] = 'utf-8' with open(fullpath, 'w', **args) as f: f.write(content) """if utf8: with codecs.open(fullpath, 'w', 'utf-8') as f: f.write(content) else: try: if lf: # ending = \n with open(fullpath, 'w', newline='') as f: f.write(content) else: # respect OS newline style with open(fullpath, 'w') as f: f.write(content) except UnicodeEncodeError: write_file(system, path, content, lf, utf8=True) """ return True else: # SSH/FTP/TFTP/HTTP # NOT IMPLEMENTED return IO_ERROR
def write_file(system, path, content, lf=True, utf8=False): fullpath = get_fullpath(system, path) if fullpath == IO_ERROR: return IO_ERROR if not can_write(system, path) and not can_create(system, path): if is_link(system, path): log.err( '\'%s\' (on %s) is a symlink to \'%s\' but it cannot be written.' % (path, system, get_link(system, path))) else: log.err('Cannot write \'%s\'.' % (fullpath)) return IO_ERROR if system.startswith('/'): # local or sub # LF? UTF-8? args = {} if lf: args['newline'] = '' if utf8: args['encoding'] = 'utf-8' try: # write file with open(fullpath, 'w', **args) as f: f.write(content) except UnicodeEncodeError: # weird char? try utf8 args['encoding'] = 'utf-8' with open(fullpath, 'w', **args) as f: f.write(content) except TypeError: # str, not bytes? write as binary with open(fullpath, 'wb') as f: f.write(content) return True else: # SSH/FTP/TFTP/HTTP # TODO NOT IMPLEMENTED return IO_ERROR
def main(): global_parameters['UUID'] = get_local_uuid() lib.active_session = db['analysis'].get_last_session() if lib.active_session is None: # Cannot get any session ID => # analysis.db is not accessible => # 'install script has not been executed' log.err('Cannot get session ID. Did you run correct installation script?') exit_program(-1, None) db['analysis'].create_session(lib.active_session) log.info('Currently working with session #%d.' % lib.active_session) # check if already admin if is_admin(): log.ok('Administrator privileges already granted on \'%s\'.' % (global_parameters['ACTIVEROOT']), dbnote=DBNOTE_UNIQUE) # if input from file, load commands into queue if args.input_file is not None: if os.access(args.input_file[0], os.R_OK): with open(args.input_file[0], 'r') as f: lib.commands = [x if x not in QUIT_STRINGS else 'force_exit' for x in f.read().splitlines()] lib.from_input_file = True else: log.err('Input file cannot be read!') # run all input commands while len(lib.commands) > 0: c = lib.commands[0] del lib.commands[0] if lib.from_input_file: log.prompt() # print prompt log.attachline(c) # print command execute_command(c) # run the command lib.from_input_file = False # main loop while True: # input from stdin, piped or redirected log.prompt() if lib.python_version[0] == '2': func = raw_input elif lib.python_version[0] == '3': func = input else: log.err('Undefined python version (%s).' % lib.python_version) break # add command into queue #lib.commands.append(func()) try: execute_command(func()) except EOFError as e: # Ctrl+D => exit exit_program(None, None)
def read_file(system, path, f=None, usedb=False, forcebinary=False, chunk=0, verbose=False): fullpath = get_fullpath(system, path) if fullpath == IO_ERROR: return IO_ERROR if not can_read(system, path): if verbose: if is_link(system, path): log.err( '\'%s\' (on \'%s\') is a symlink to \'%s\' but it cannot be read.' % (path, system, get_link(system, path))) else: log.err('Cannot read \'%s\'.' % (fullpath)) return IO_ERROR open_and_close = (f is None) if system.startswith('/'): # local or sub if open_and_close: try: if forcebinary: raise TypeError # will be opened as binary f = open(fullpath, 'r', encoding='utf-8') except: # a binary file? f = open(fullpath, 'rb') result = f.read() if chunk == 0 else f.read(chunk) if open_and_close: f.close() if usedb == True or usedb == DBFILE_NOCONTENT: fileinfo = get_file_info(system, path) if fileinfo == IO_ERROR: return IO_ERROR # cannot access file info - something is weird add = db['analysis'].add_file(system, path, fileinfo['type'], fileinfo['permissions'], fileinfo['UID'], fileinfo['GID'], result if usedb else None, fileinfo['ATIME'], fileinfo['MTIME'], fileinfo['CTIME']) if not add: log.err('Database query failed.') return IO_ERROR return result elif system.startswith('ssh://'): c = get_ssh_connection(system) if c is not None: if open_and_close: try: sftp = c.connectors[0].open_sftp() except: log.err('Cannot create SFTP connection.') return IO_ERROR try: if forcebinary: raise TypeError # will be treated as binary f = sftp.open(path, 'r') except: f = sftp.open(path, 'rb') result = f.read() if chunk == 0 else f.read(size=chunk) if open_and_close: sftp.close() if forcebinary: return result else: return result.decode('utf-8') else: log.err('Cannot read file on \'%s\' - no such connection' % (system)) return IO_ERROR # TODO usedb, chunk etc. else: # FTP/TFTP/HTTP # TODO NOT IMPLEMENTED return IO_ERROR
def search(expression): # build a tree from expression and run eval() on root priority = ['', '|', '&', '!', '('] # '' won't be there (filtered in Split()) depth = 0 nodes = [] operators = [ ] # determined by priority (mod 4 gives index in priority list) expression = list( filter(None, [ x.strip() for x in re.split(r'([! \(\)<>=]|&&|\|\|)', expression) ])) #print(expression) for x in expression: # first normalize operators (&&, &, and) ... if x.lower() in ['&&', 'and']: x = '&' if x.lower() in ['||', 'or']: x = '|' if x.lower() in ['not']: x = '!' #now build a tree if x == ')': depth -= 1 if depth < 0: log.err('Your query is broken (brackets in wrong order).') return [] elif x in priority: # operand # use parameters with lower priority while len(operators) > 0 and (4 * depth + priority.index(x)) < operators[-1]: if operators[-1] % 4 == 1: # OR if len(nodes) < 2: log.err('Your query is broken (missing OR operands).') return [] nodes.append(Or(nodes.pop(), nodes.pop())) operators.pop() elif operators[-1] % 4 == 2: # AND if len(nodes) < 2: log.err('Your query is broken (missing AND operands).') return [] nodes.append(And(nodes.pop(), nodes.pop())) operators.pop() elif operators[-1] % 4 == 3: # NOT if len(nodes) < 1: log.err('Your query is broken (missing NOT operand).') return [] nodes.append(Not(nodes.pop())) operators.pop() else: # ( log.err('Your query is broken (undefined behaviour).') # push operator priority if priority.index(x) % 4 == 0: depth += 1 else: operators.append(4 * depth + priority.index(x)) else: # operand nodes.append(Leaf(x)) # everything processed, use remaining operators while len(operators) > 0: if operators[-1] % 4 == 1: # OR if len(nodes) < 2: log.err('Your query is broken (missing OR operands).') return [] nodes.append(Or(nodes.pop(), nodes.pop())) operators.pop() elif operators[-1] % 4 == 2: # AND if len(nodes) < 2: log.err('Your query is broken (missing AND operands).') return [] nodes.append(And(nodes.pop(), nodes.pop())) operators.pop() elif operators[-1] % 4 == 3: # NOT if len(nodes) < 1: log.err('Your query is broken (missing NOT operand).') return [] nodes.append(Not(nodes.pop())) operators.pop() if depth != 0: log.err('Your query is broken (brackets are not paired).') return [] if len(nodes) != 1: log.err('Your query is broken (too many operands).') return [] return nodes[0].eval()