def _get_violation_events(sieve, input_auth, attributes, indent): try: auth = _process_auth_list(input_auth, indent) except json.decoder.JSONDecodeError as e: raise USBRipError( 'Failed to decode authorized device list (JSON)', errors={'initial_error': str(e)} ) if not attributes: attributes = auth.keys() ue = USBEvents() if not ue: return None for event in ue._all_events: try: if any(event[key] not in vals and event[key] is not None for key, vals in zip(attributes, auth.values())): ue._violations.append(event) except KeyError as e: raise USBRipError( 'No such attribute in authorized device list', errors={'initial_error': str(e)} ) return _filter_events(ue._violations, sieve)
def _get_filtered_history(): filtered_history = [] print_info( 'Searching for log files: "/var/log/syslog*" or "/var/log/messages*"') syslog_files = sorted([ filename for filename in list_files('/var/log/') if filename.rsplit('/', 1)[1].startswith('syslog') ]) if syslog_files: for syslog in syslog_files: filtered_history.extend(_read_log_file(syslog)) else: messages_files = sorted([ filename for filename in list_files('/var/log/') if filename.rsplit('/', 1)[1].startswith('messages') ]) if messages_files: for messages in messages_files: filtered_history.extend(_read_log_file(messages)) else: raise USBRipError('None of log file types was found!') return filtered_history
def _dump_events(events_to_show, list_name, abs_filename, indent): print_info(f'Generating {list_name} list (JSON)') out = [] for event in events_to_show: tmp_event_dict = OrderedDict() for key in ('conn', 'host', 'vid', 'pid', 'prod', 'manufact', 'serial', 'port', 'disconn'): tmp_event_dict[key] = event[key] out.append(tmp_event_dict) try: with open(abs_filename, 'w', encoding='utf-8') as out_json: json.dump(out, out_json, indent=indent) except PermissionError as e: raise USBRipError( f'Permission denied: "{abs_filename}". Retry with sudo', errors={'initial_error': str(e)} ) os.chmod(abs_filename, stat.S_IRUSR | stat.S_IWUSR) # 600 print_info(f'New {list_name} list: "{abs_filename}"')
def _get_raw_history(): raw_history = DefaultOrderedDict(default_factory=list) print_info( 'Searching for log files: "/var/log/syslog*" or "/var/log/messages*"') syslog_files = sorted([ filename for filename in list_files('/var/log/') if filename.rsplit('/', 1)[1].startswith('syslog') ]) if syslog_files: for syslog in syslog_files: raw_history.update(_read_log_file(syslog)) else: messages_files = sorted([ filename for filename in list_files('/var/log/') if filename.rsplit('/', 1)[1].startswith('messages') ]) if messages_files: for messages in messages_files: raw_history.update(_read_log_file(messages)) else: raise USBRipError('None of log file types was found!') return raw_history
def _get_filtered_history(): filtered_history = [] print_info( 'Searching for log files: C:\\Users\\eyver-dev\\Documents\\python\\usbrip\\test\\syslog* or C:\\Users\\eyver-dev\\Documents\\python\\usbrip\\test\\messages*' ) syslog_files = sorted([ filename for filename in list_files( 'C:\\Users\\eyver-dev\\Documents\\python\\usbrip\\test') if filename.rsplit('\\', 1)[1].startswith('syslog') ]) if syslog_files: for syslog in syslog_files: filtered_history.extend(_read_log_file(syslog)) else: messages_files = sorted([ filename for filename in list_files('/var/log/') if filename.rsplit('/', 1)[1].startswith('messages') ]) if messages_files: for messages in messages_files: filtered_history.extend(_read_log_file(messages)) else: raise USBRipError('None of log file types was found!') return filtered_history
def _read_log_file(filename): filtered = [] abs_filename = os.path.abspath(filename) if abs_filename.endswith('.gz'): print_info(f'Unpacking "{abs_filename}"') try: log = gzip.open(abs_filename, 'rb') except PermissionError as e: print_warning( f'Permission denied: "{abs_filename}". Retry with sudo', initial_error=str(e)) return filtered else: end_of_file = b'' abs_filename = os.path.splitext(abs_filename) else: log = codecs.open(abs_filename, 'r', encoding='utf-8', errors='ignore') end_of_file = '' print_info(f'Reading "{abs_filename}"') regex = re.compile(r'] usb (.*?): ') for line in iter(log.readline, end_of_file): if isinstance(line, bytes): line = line.decode(encoding='utf-8', errors='ignore') if regex.search(line): date = line[:32] if date.count(':') > 2: date = ''.join( line[:32].rsplit(':', 1) ) # rreplace(':', 1) to remove the last ':' from "2019-08-09T06:15:49.655261-04:00" timestamp if there is one try: date = datetime.strptime( date, '%Y-%m-%dT%H:%M:%S.%f%z' ) # ex. 2019-08-09T06:15:49.655261-0400 except ValueError as e: raise USBRipError( f'Wrong timestamp format found in "{abs_filename}"', errors={'initial_error': str(e)}) else: date = date.strftime('%Y-%m-%d %H:%M:%S') logline = line[32:].strip() if any(pat in line for pat in ('New USB device found, ', 'Product: ', 'Manufacturer: ', 'SerialNumber: ')): filtered.append((date, 'c', logline)) elif 'disconnect' in line: filtered.append((date, 'd', logline)) log.close() return filtered
def _download_database(filename): try: dirname = os.path.dirname(filename) os_makedirs(dirname) except USBRipError as e: raise USBRipError(str(e), errors={'initial_error': e.errors['initial_error']}) else: print_info(f'Created directory "{dirname}/"') try: usb_ids = open(filename, 'w+', encoding='utf-8') except PermissionError as e: raise USBRipError(f'Permission denied: "{filename}"', errors={'initial_error': str(e)}) db, latest_ver, latest_date, errcode, e = _get_latest_version() if errcode: usb_ids.close() os.remove(filename) if errcode == USBIDs._INTERNET_CONNECTION_ERROR: errmsg = 'No internet connection' elif errcode == USBIDs._SERVER_TIMEOUT_ERROR: errmsg = 'Server timeout' elif errcode == USBIDs._SERVER_CONTENT_ERROR: errmsg = 'Server content error: no version or date found' raise USBRipError(errmsg, errors={ 'errcode': errcode, 'initial_error': e }) usb_ids.write(db) usb_ids.seek(0) print_info('Database downloaded') print(f'Version: {latest_ver}') print(f'Date: {latest_date}') return usb_ids
def _update_database(filename): try: usb_ids = open(filename, 'r+', encoding='utf-8') except PermissionError as e: raise USBRipError( f'Permission denied: "{filename}"', errors={'initial_error': str(e)} ) print_info('Getting current database version') curr_ver, curr_date = _get_current_version(usb_ids) print(f'Version: {curr_ver}') print(f'Date: {curr_date}') print_info('Checking local database for update') db, latest_ver, latest_date, errcode, e = _get_latest_version() if errcode: if errcode == USBIDs._INTERNET_CONNECTION_ERROR: print_warning( 'No internet connection, using current version', errcode=errcode ) elif errcode == USBIDs._SERVER_TIMEOUT_ERROR: print_warning( 'Server timeout, using current version', errcode=errcode, initial_error=e ) elif errcode == USBIDs._SERVER_CONTENT_ERROR: print_warning( 'Server error, using current version', errcode=errcode, initial_error=e ) return usb_ids if curr_ver != latest_ver and curr_date != latest_date: # if there's newer database version print('Updating database... ', end='') usb_ids.write(db) usb_ids.truncate() usb_ids.seek(0) print('Done\n') print(f'Version: {latest_ver}') print(f'Date: {latest_date}') print_info('Local database is up-to-date') return usb_ids
def _get_current_version(usb_ids): db = usb_ids.read() usb_ids.seek(0) try: curr_ver = re.search(r'^# Version:\s*(.*?$)', db, re.MULTILINE).group(1) curr_date = re.search(r'^# Date:\s*(.*?$)', db, re.MULTILINE).group(1) except AttributeError as e: raise USBRipError( 'Invalid database content structure: no version or date found', errors={'initial_error': str(e)}) return (curr_ver, curr_date)
def _7zip_list(archive, password): print_info(f'Listing archive: "{archive}"') cmd = ['7z', 'l', archive, '-p' + password] out, errcode, errmsg, e = _7zip_subprocess_handler(cmd) if errcode: raise USBRipError(errmsg, errors={ 'errcode': errcode, 'initial_error': e }) return out
def prepare_database(*, offline=True): filename = f'{os.path.abspath(str(Path.home()))}/.config/usbrip/usb.ids' file_exists = os.path.isfile(filename) if file_exists and offline: usb_ids = open(filename, 'r', encoding='utf-8') elif file_exists and not offline: usb_ids = _update_database(filename) elif not file_exists and not offline: print_warning('No local database found, trying to download') usb_ids = _download_database(filename) elif not file_exists and offline: raise USBRipError('No local database found') return usb_ids
def prepare_database(*, offline=True): filename = root_dir_join('usb_ids/usb.ids') file_exists = os.path.isfile(filename) if file_exists and offline: usb_ids = open(filename, 'r', encoding='utf-8') elif file_exists and not offline: usb_ids = _update_database(filename) elif not file_exists and not offline: print_warning('No local database found, trying to download') usb_ids = _download_database(filename) elif not file_exists and offline: raise USBRipError('No local database found') return usb_ids
def _7zip_unpack(archive, password): print_info(f'Unpacking archive: "{archive}"') cmd = [ '7z', 'e', archive, '-p' + password, '-o' + USBStorage._STORAGE_BASE, '-y' ] out, errcode, errmsg, e = _7zip_subprocess_handler(cmd) if errcode: raise USBRipError(errmsg, errors={'errcode': errcode, 'initial_error': e}) return out
def _7zip_pack(archive, file, password, compression_level): print_info(f'Creating storage (7-Zip): "{archive}"') cmd = [ '7z', 'a', archive, file, '-mhe=on', '-p' + password, '-mx=' + compression_level ] out, errcode, errmsg, e = _7zip_subprocess_handler(cmd) if errcode: raise USBRipError(errmsg, errors={ 'errcode': errcode, 'initial_error': e }) return out
def _dump_events(events_to_show, list_name, filename, indent): print_info('Generating {} list (JSON)'.format(list_name)) out = [] for event in events_to_show: tmp_event_dict = OrderedDict() for key in ('conn', 'user', 'vid', 'pid', 'prod', 'manufact', 'serial', 'port', 'disconn'): tmp_event_dict[key] = event[key] out.append(tmp_event_dict) try: with open(filename, 'w', encoding='utf-8') as out_json: json.dump(out, out_json, indent=indent) except PermissionError as e: raise USBRipError( 'Permission denied: \'{}\'. Retry with sudo'.format(filename), errors={'initial_error': str(e)} ) print_info('New {} list: \'{}\''.format(list_name, os.path.abspath(filename)))
def _read_log_file(filename, log=None): filtered = [] if log is None: abs_filename = os.path.abspath(filename) if abs_filename.endswith('.gz'): print_info(f'Unpacking "{abs_filename}"') try: log = gzip.open(abs_filename, 'rb') except PermissionError as e: print_warning( f'Permission denied: "{abs_filename}". Retry with sudo', initial_error=str(e)) return filtered else: end_of_file = b'' abs_filename = os.path.splitext(abs_filename) else: log = codecs.open(abs_filename, 'r', encoding='utf-8', errors='ignore') end_of_file = '' print_info(f'Reading "{abs_filename}"') else: abs_filename = 'journalctl output' end_of_file = '' print_info(f'Reading journalctl output') regex = re.compile(r'(?:]|:) usb (.*?): ') for line in tqdm(iter(log.readline, end_of_file), unit='line'): if isinstance(line, bytes): line = line.decode('utf-8', errors='ignore') if regex.search(line): # Case 1 -- Modified Timestamp ("%Y-%m-%dT%H:%M:%S.%f%z") date = line[:32].strip() if date.count(':') == 3: date = ''.join( line[:32].rsplit(':', 1) ) # rreplace(':', '', 1) to remove the last ':' from "2019-08-09T06:15:49.655261-04:00" timestamp if there is one try: date = datetime.strptime( date, '%Y-%m-%dT%H:%M:%S.%f%z' ) # ex. "2019-08-09T06:15:49.655261-0400" except ValueError: # Case 2 -- Non-Modified Timestamp ("%b %d %H:%M:%S") date = line[:15].strip() if ' ' in date: date = date.replace(' ', ' 0', 1) # pad day of the week with zero try: date = datetime.strptime( date, '%b %d %H:%M:%S') # ex. "Mar 18 13:56:07" except ValueError as e: raise USBRipError( f'Wrong timestamp format found in "{abs_filename}"', errors={'initial_error': str(e)}) else: date = date.strftime('????-%m-%d %H:%M:%S') logline = line[15:].strip() else: date = date.strftime('%Y-%m-%d %H:%M:%S') logline = line[32:].strip() if any(pat in line for pat in ('New USB device found, ', 'Product: ', 'Manufacturer: ', 'SerialNumber: ')): filtered.append((date, 'c', logline)) elif 'disconnect' in line: filtered.append((date, 'd', logline)) log.close() return filtered