def event_history(self, columns, *, sieve=None, repres=None, quiet=None): if columns: table_data = [[COLUMN_NAMES[name] for name in columns]] else: columns = [key for key in COLUMN_NAMES.keys()] table_data = [[val for val in COLUMN_NAMES.values()]] self._events_to_show = _filter_events(self._all_events, sieve) if not self._events_to_show: print_info('No USB events found!') return if not quiet: try: number, filename = _output_choice('event history', 'history.json', 'history/') except USBRipError as e: print_critical(str(e), initial_error=e.errors['initial_error']) return if number == '1': _json_dump(self._events_to_show, 'event history', filename) return _represent_events(self._events_to_show, columns, table_data, 'USB-History-Events', repres)
def generate_auth_json(self, output_auth): try: os_makedirs(os.path.dirname(output_auth)) except USBRipError as e: print_critical(str(e), initial_error=e.errors['initial_error']) return try: auth_json = open(output_auth, 'w') except PermissionError as e: print_critical('Permission denied: \'{}\''.format(output_auth), initial_error=str(e)) return print_info('Generating authorized device list (JSON)') auth = defaultdict(list) for event in self._all_events: for key, val in event.items(): if key in ('vid', 'pid', 'prod', 'manufact', 'serial') and \ val is not None and \ val not in auth[key]: auth[key].append(val) for key in auth.keys(): auth[key].sort() json.dump(auth, auth_json, sort_keys=True, indent=4) auth_json.close() print_info('New authorized device list: \'{}\''.format(output_auth))
def search_ids(vid, pid, *, offline=True): if offline: print_warning('Offline mode') try: usb_ids = USBIDs.prepare_database(offline=offline) except USBRipError as e: print_critical(str(e), errcode=e.errors['errcode'], initial_error=e.errors['initial_error']) else: _search_ids_helper(usb_ids, vid, pid) usb_ids.close()
def _output_choice(list_name, default_filename, dirname): while True: print('[?] How would you like your {} list to be generated?\n'.format( list_name)) print(' 1. JSON-file') print(' 2. Terminal stdout') number = input('\n[>] Please enter the number of your choice: ') if number == '1': while True: filename = input('[>] Please enter the base name for the output file ' \ '(default is \'{}\'): '.format(default_filename)) if all(c in printable for c in filename) and len(filename) < 256: if not filename: filename = default_filename elif filename[-5:] != '.json': filename = filename + '.json' filename = root_dir_join(dirname + filename) try: dirname = os.path.dirname(filename) os_makedirs(dirname) except USBRipError as e: print_critical(str(e), initial_error=e.errors['initial_error']) return (None, '') else: print_info('Created \'{}\''.format(dirname)) overwrite = True if os.path.exists(filename): while True: overwrite = input( '[?] File exists. Would you like to overwrite it? [Y/n]: ' ) if len(overwrite) == 1 and overwrite in 'Yy': overwrite = True break elif len(overwrite) == 1 and overwrite in 'Nn': overwrite = False break if overwrite: return (int(number), filename) elif number == '2': return (int(number), '')
def search_violations(self, input_auth, columns, *, sieve=None, repres=None): try: auth = _process_auth_json(input_auth) except json.decoder.JSONDecodeError as e: print_critical('Failed to decode authorized device list (JSON)', initial_error=str(e)) return if columns: table_data = [[COLUMN_NAMES[name] for name in columns]] else: columns = [key for key in COLUMN_NAMES.keys()] table_data = [[val for val in COLUMN_NAMES.values()]] print_info('Searching for violations', quiet=USBEvents.QUIET) for event in self._all_events: try: if any(event[key] not in vals and event[key] is not None for key, vals in auth.items()): self._violations.append(event) except KeyError as e: print_critical( 'Invalid structure of authorized device list (JSON)', initial_error=str(e)) return self._events_to_show = _filter_events(self._violations, sieve) if not self._events_to_show: print_info('No USB violation events found!', quiet=USBEvents.QUIET) json.dump([], auth_json) auth_json.close() return if not USBEvents.QUIET and ISATTY: number, filename = _output_choice('violation', 'viol.json', 'violations/') if number is None: return elif number == 1: _json_dump(self._events_to_show, 'violation', filename) return _represent_events(self._events_to_show, columns, table_data, 'USB-Violation-Events', repres)
def __init__(self, files=None): if files: raw_history = DefaultOrderedDict(list) for file in files: raw_history.update(_read_log_file(file)) else: try: raw_history = _get_raw_history() except USBRipError as e: print_critical(str(e)) divided_history = _divide_history(raw_history) self._all_events = _parse_history(divided_history) self._violations, self._events_to_show = [], None
def _update_database(filename): try: usb_ids = open(filename, 'r+') except PermissionError as e: print_critical('Permission denied: \'{}\''.format(filename), initial_error=str(e)) return curr_ver, curr_date = _get_current_version(usb_ids) print_info('Getting current database version') print('Version: {}'.format(curr_ver)) print('Date: {}'.format(curr_date)) print_info('Checking local database for update') db, latest_ver, latest_date, error, e = _get_latest_version() if error: if error == USBIDs._INTERNET_CONNECTION_ERROR: print_warning('No internet connection, using current version', errcode=error) elif error == USBIDs._SERVER_TIMEOUT_ERROR: print_warning('Server timeout, using current version', errcode=error, initial_error=e) elif error == USBIDs._SERVER_CONTENT_ERROR: print_warning('Server error, using current version', errcode=error, 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.seek(0) usb_ids.truncate() print('Done\n') print('Version: {}'.format(latest_ver)) print('Date: {}'.format(latest_date)) print_info('Local database is up-to-date') return usb_ids
def _download_database(filename): try: os_makedirs(os.path.dirname(filename)) except USBRipError as e: print_critical(str(e), initial_error=e.errors['initial_error']) return try: usb_ids = open(filename, 'w+') except PermissionError as e: print_critical('Permission denied: \'{}\''.format(filename), initial_error=str(e)) return db, latest_ver, latest_date, error, e = _get_latest_version() if error: usb_ids.close() os.remove(filename) if error == USBIDs._INTERNET_CONNECTION_ERROR: raise USBRipError('No internet connection') elif error == USBIDs._SERVER_TIMEOUT_ERROR: raise USBRipError('Server timeout', errors={ 'errcode': error, 'initial_error': e }) elif error == USBIDs._SERVER_CONTENT_ERROR: raise USBRipError('Server content error: no version or date found', errors={ 'errcode': error, 'initial_error': e }) usb_ids.write(db) usb_ids.seek(0) print_info('Database downloaded') print('Version: {}'.format(latest_ver)) print('Date: {}'.format(latest_date)) return usb_ids
def _json_dump(events_to_show, list_name, filename): print_info('Generating {} list (JSON)'.format(list_name)) out = OrderedDict() for event in events_to_show: out[event['conn']] = OrderedDict() for key, val in sorted(event.items()): if key != 'conn': out[event['conn']][key] = val try: with open(filename, 'w') as out_json: json.dump(out, out_json, indent=4) except PermissionError as e: print_critical('Permission denied: \'{}\''.format(filename), initial_error=str(e)) return print_info('New {} list: \'{}\''.format(list_name, filename))
def generate_auth_json(self, output_auth, *, sieve=None): try: dirname = os.path.dirname(filename) os_makedirs(dirname) except USBRipError as e: print_critical(str(e), initial_error=e.errors['initial_error']) return else: print_info('Created \'{}\''.format(dirname)) try: auth_json = open(output_auth, 'w') except PermissionError as e: print_critical('Permission denied: \'{}\''.format(output_auth), initial_error=str(e)) return self._events_to_show = _filter_events(self._all_events, sieve) if not self._events_to_show: print_info('No USB violation events found!', quiet=USBEvents.QUIET) json.dump([], auth_json) auth_json.close() return print_info('Generating authorized device list (JSON)', quiet=USBEvents.QUIET) auth = defaultdict(list) for event in self._events_to_show: for key, val in event.items(): if key in ('vid', 'pid', 'prod', 'manufact', 'serial') and \ val is not None and \ val not in auth[key]: auth[key].append(val) for key in auth.keys(): auth[key].sort() json.dump(auth, auth_json, sort_keys=True, indent=4) auth_json.close() print_info('New authorized device list: \'{}\''.format(output_auth), quiet=USBEvents.QUIET)
def search_violations(self, input_auth, *, sieve=None, repres=None, quiet=None): try: auth = _process_auth_json(input_auth) except json.decoder.JSONDecodeError as e: print_critical('Failed to decode authorized device list (JSON)', initial_error=str(e)) return print_info('Searching for violations') for event in self._all_events: try: if any(event[key] not in vals and event[key] is not None for key, vals in auth.items()): self._violations.append(event) except KeyError as e: print_critical( 'Invalid structure of authorized device list (JSON)', initial_error=str(e)) return columns = [key for key in COLUMN_NAMES.keys()] table_data = [[val for val in COLUMN_NAMES.values()]] self._events_to_show = _filter_events(self._violations, sieve) if not self._events_to_show: print_info('No USB violation events found!') return if not quiet: try: number, filename = _output_choice('violation', 'viol.json', 'violations/') except USBRipError as e: print_critical(str(e), initial_error=e.errors['initial_error']) return if number == '1': _json_dump(self._events_to_show, 'violation', filename) return _represent_events(self._events_to_show, columns, table_data, 'USB-Violation-Events', repres)
def main(): if not len(sys.argv) > 1: print(BANNER + '\n') usbrip_error('No arguments were passed') parser = cmd_line_options() args = parser.parse_args() if 'quiet' in args and not args.quiet: print(BANNER + '\n') # ---------------------------------------------------------- # ------------------------- Banner ------------------------- # ---------------------------------------------------------- if args.subparser == 'banner': print(BANNER) # ---------------------------------------------------------- # ----------------------- USB Events ----------------------- # ---------------------------------------------------------- elif args.subparser == 'events' and args.ue_subparser: if 'columns' in args and args.columns: for name in args.columns: if name not in COLUMN_NAMES.keys(): usbrip_error(name + ': Invalid column name') if 'date' in args and args.date: re_date = re.compile( r'^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [\s1-3][0-9]$' ) for date in args.date: if not re_date.search(date): usbrip_error(date + ': Wrong date format') if 'file' in args and args.file: for file in args.file: if not os.path.exists(file): usbrip_error(file + ': Path does not exist') sieve = dict( zip(('external', 'number', 'date'), (args.external, args.number, args.date))) repres = dict.fromkeys(('table', 'list', 'smart'), False) if 'table' in args and args.table: repres['table'] = True elif 'list' in args and args.list: repres['list'] = True else: repres['smart'] = True # ------------------- USB Events History ------------------- if args.ue_subparser == 'history': ueh = USBEvents(args.file, quiet=args.quiet) ueh.event_history(args.columns, sieve=sieve, repres=repres) # ---------------- USB Events Gen Auth JSON ---------------- elif args.ue_subparser == 'gen_auth': if os.path.exists(args.output): usbrip_error(args.output + ': Path already exists') ueg = USBEvents(args.file, quiet=args.quiet) ueg.generate_auth_json(args.output, sieve=sieve) # ----------------- USB Events Violations ------------------ elif args.ue_subparser == 'violations': if not os.path.exists(args.input): usbrip_error(args.input + ': Path does not exist') uev = USBEvents(args.file, quiet=args.quiet) uev.search_violations(args.input, args.columns, sieve=sieve, repres=repres) # ---------------------------------------------------------- # ------------------------ USB IDs ------------------------- # ---------------------------------------------------------- elif args.subparser == 'ids' and args.ui_subparser: ui = USBIDs(quiet=args.quiet) # --------------------- USB IDs Search --------------------- if args.ui_subparser == 'search': if not args.vid and not args.pid: usbrip_error( 'At least one of --vid/--pid or --download option should be specified' ) ui.search_ids(args.vid, args.pid, offline=args.offline) # -------------------- USB IDs Download -------------------- elif args.ui_subparser == 'download': try: usb_ids = ui.prepare_database(offline=False) except USBRipError as e: print_critical(str(e), errcode=e.errors['errcode'], initial_error=e.error['initial_error']) else: usb_ids.close() else: subparser = ' ' + args.subparser + ' ' usbrip_error('Choose one of the usbrip {} actions'.format( args.subparser), subparser=subparser)