예제 #1
0
def get_config_parser():
	config_parser = ConfigParser(allow_no_value=True)
	config_parser.optionxform = str

	os.makedirs(CONFIG_FILE.rsplit('/', 1)[0], exist_ok=True)

	if os.path.isfile(CONFIG_FILE):
		config_parser.read(CONFIG_FILE, encoding='utf-8')
		print_info(f'Configuration loaded: "{CONFIG_FILE}"')

	else:
		print_warning('No configuration file found, creating new one...')

		config_parser.add_section('history')
		config_parser.set('history', 'password', 'r1pp3r')

		config_parser.add_section('violations')
		config_parser.set('violations', 'password', 'r1pp3r')

		print_info(f'New configuration file: "{CONFIG_FILE}"')

		with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
			config_parser.write(f)

	return config_parser
예제 #2
0
def _read_log_file(filename):
    filtered = DefaultOrderedDict(default_factory=list)

    if filename.endswith('.gz'):
        print_info(f'Unpacking "{filename}"')

        try:
            log = gzip.open(filename, 'rb')
        except PermissionError as e:
            print_warning(f'Permission denied: "{filename}". Retry with sudo',
                          initial_error=str(e))
            return filtered
        else:
            end_of_file = b''
            filename = filename[:-3]

    else:
        log = codecs.open(filename, 'r', encoding='utf-8', errors='ignore')
        end_of_file = ''

    print_info(f'Reading "{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):
            filtered[line[:15]].append(line)  # line[:15] == 'Mon dd hh:mm:ss'

    log.close()
    return filtered
예제 #3
0
파일: usbevents.py 프로젝트: todun/usbrip
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
예제 #4
0
파일: usbids.py 프로젝트: zan00789/usbrip
	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()
예제 #5
0
	def __new__(cls, files=None):
		try:
			if files:
				filtered_history = []
				for file in files:
					filtered_history.extend(_read_log_file(file))

			else:
				print_info('Trying to run journalctl...')

				# child_env = os.environ.copy()
				# child_env['LANG'] = 'en_US.utf-8'
				# journalctl_out = check_output(['journalctl'], env=child_env).decode('utf-8')

				try:
					journalctl_out = check_output([
						'journalctl',
						'-o',
						'short-iso-precise'
					]).decode('utf-8')

				except Exception as e:
					print_warning(f'Failed to run journalctl: {str(e)}')
					filtered_history = _get_filtered_history()

				else:
					if '-- Logs begin at' in journalctl_out:
						print_info('Successfully ran journalctl')

						filtered_history = _read_log_file(
							None,
							log=StringIO(journalctl_out),
							total=journalctl_out.count('\n')
						)

					else:
						print_warning(f'An error occurred when running journalctl: {journalctl_out}')
						filtered_history = _get_filtered_history()

		except USBRipError as e:
			print_critical(str(e), initial_error=e.errors['initial_error'])
			return None

		all_events = _parse_history(filtered_history)

		instance = super().__new__(cls)
		instance._all_events = all_events  # self._all_events
		instance._violations = []          # self._violations
		instance._events_to_show = None    # self._events_to_show
		return instance
예제 #6
0
    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
예제 #7
0
def _shred(filename):
	cmd = [
		'shred',
		'-z',
		'-u',
		'-n',
		'7',
		filename
	]

	try:
		out = subprocess.check_output(cmd).decode('utf-8')
	except subprocess.CalledProcessError as e:
		print_warning(f'Failed to shred {filename}, using standard rm instead: {str(e)}')
		os.remove(filename)
예제 #8
0
파일: usbids.py 프로젝트: fo0nikens/usbrip
    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
예제 #9
0
def _filter_events(all_events, sieve):
    if sieve is None:
        sieve = {'external': False, 'number': -1, 'dates': [], 'fields': {}}

    if sieve != {'external': False, 'number': -1, 'dates': [], 'fields': {}}:
        print_info('Filtering events')

    events_to_show = all_events

    if sieve['fields']:
        events_to_show = []
        for key, vals in sieve['fields'].items():
            events_to_show += [
                event for event in all_events for val in vals
                if event[key] == val
            ]

    if sieve['external']:
        events_to_show = [
            event for event in all_events if event['disconn'] is not None
        ]

    if sieve['dates']:
        events_to_show = [
            event for date in sieve['dates'] for event in events_to_show
            if event['conn'][:6] == date
        ]

    if not events_to_show:
        return []

    SIZE = len(events_to_show)
    if sieve['number'] == -1 or sieve['number'] >= SIZE:
        if sieve['number'] > SIZE:
            print_warning(
                f'USB action history has only {SIZE} entries instead of requested {sieve["number"]}, '
                f'displaying all of them...')

        sieve['number'] = SIZE

    return [events_to_show[SIZE - i] for i in range(sieve['number'], 0, -1)]
예제 #10
0
파일: usbids.py 프로젝트: zan00789/usbrip
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
예제 #11
0
파일: usbevents.py 프로젝트: todun/usbrip
def _represent_events(events_to_show, columns, table_data, title, repres):
    print_info('Preparing gathered events')

    if repres is None:
        repres = {'table': False, 'list': False, 'smart': True}

    max_len = {
        'conn':
        19,
        'user':
        max(max(len(event['user']) for event in events_to_show), len('User')),
        'vid':
        4,
        'pid':
        4,
        'prod':
        max(max(len(str(event['prod'])) for event in events_to_show),
            len('Product')),
        'manufact':
        max(max(len(str(event['manufact'])) for event in events_to_show),
            len('Manufacturer')),
        'serial':
        max(max(len(str(event['serial'])) for event in events_to_show),
            len('Serial Number')),
        'port':
        max(max(len(event['port']) for event in events_to_show), len('Port')),
        'disconn':
        19
    }

    prev_cday = ''
    for event in events_to_show:
        if 'conn' in columns:
            curr_cday = event['conn'][:10]
            if prev_cday != curr_cday:
                cday = [
                    f'{curr_cday} {BULLET * (len(event["conn"])-len(curr_cday)-1)}'
                ]
                table_data.append(cday + [
                    SEPARATOR * max_len[name]
                    for name in columns if name != 'conn'
                ])
            prev_cday = curr_cday

        row = []
        for name in columns:
            if event[name] is None:
                event[name] = ABSENCE

            item = event[name]
            if name == 'conn' and cfg.ISATTY:
                item = colored(item, 'green')
            elif name == 'disconn' and cfg.ISATTY:
                item = colored(item, 'red')

            row.append(item)

        table_data.append(row)

    event_table = _build_single_table(USBEvents.TableClass, table_data,
                                      colored(title, 'white', attrs=['bold']))

    # Display as table
    if cfg.ISATTY and (repres['smart'] and event_table.ok or repres['table']):
        print_info('Representation: Table')
        print('\n' + event_table.table)

    # Display as list
    elif not cfg.ISATTY or (repres['smart'] and not event_table.ok
                            or repres['list']):
        if not event_table.ok:
            print_warning(
                'Terminal window is too small to display table properly')
            print_warning('Representation: List')
        else:
            print_info('Representation: List')

        max_len = max(
            len(str(val))
            for event in events_to_show for val in event.values()) + len(
                'Serial Number:  ')  # max length string
        if not max_len // 2:
            max_len += 1

        if cfg.ISATTY:
            cprint('\n' + title, 'white', attrs=['bold'])
        else:
            print('\n' + title)

        print(SEPARATOR * max_len)

        for event in events_to_show:
            if cfg.ISATTY:
                print(
                    colored('Connected:      ', 'magenta', attrs=['bold']) +
                    colored(event['conn'], 'green'))
                print(
                    colored('User:           '******'magenta', attrs=['bold']) +
                    event['user'])
                print(
                    colored('VID:            ', 'magenta', attrs=['bold']) +
                    event['vid'])
                print(
                    colored('PID:            ', 'magenta', attrs=['bold']) +
                    event['pid'])
                print(
                    colored('Product:        ', 'magenta', attrs=['bold']) +
                    str(event['prod']))
                print(
                    colored('Manufacturer:   ', 'magenta', attrs=['bold']) +
                    str(event['manufact']))
                print(
                    colored('Serial Number:  ', 'magenta', attrs=['bold']) +
                    str(event['serial']))
                print(
                    colored('Bus-Port:       ', 'magenta', attrs=['bold']) +
                    event['port'])
                print(
                    colored('Disconnected:   ', 'magenta', attrs=['bold']) +
                    colored(event['disconn'], 'red'))
            else:
                print('Connected:      ' + event['conn'])
                print('User:           '******'user'])
                print('VID:            ' + event['vid'])
                print('PID:            ' + event['pid'])
                print('Product:        ' + str(event['prod']))
                print('Manufacturer:   ' + str(event['manufact']))
                print('Serial Number:  ' + str(event['serial']))
                print('Bus-Port:       ' + event['port'])
                print('Disconnected:   ' + event['disconn'])

            print(SEPARATOR * max_len)
예제 #12
0
파일: usbevents.py 프로젝트: todun/usbrip
def _filter_events(all_events, sieve):
    # sieve = {
    #    'external': False,
    #    'dates':       [],
    #    'fields':      {},
    #    'number':      -1
    # }

    if sieve is None:
        return all_events

    else:
        print_info('Filtering events')

        events_by_external = []
        if sieve['external']:
            for event in all_events:
                if event['disconn'] is not None:
                    events_by_external.append(event)
                    continue
        else:
            events_by_external = all_events

        events_by_date = []
        if sieve['dates']:
            for event in all_events:
                for date in sieve['dates']:
                    if event['conn'].startswith(date):
                        events_by_date.append(event)
                        break
                continue
        else:
            events_by_date = all_events

        event_intersection = intersect_event_sets(events_by_external,
                                                  events_by_date)

        events_to_show = []
        if sieve['fields']:
            for event in event_intersection:
                for key, vals in sieve['fields'].items():
                    if any(event[key] == val for val in vals):
                        events_to_show.append(event)
                        break
        else:
            events_to_show = event_intersection

        if not events_to_show:
            return []

        SIZE = len(events_to_show)
        if sieve['number'] <= -1 or sieve['number'] > SIZE:
            if sieve['number'] < -1:
                print_warning(
                    f'usbrip can\'t handle dark matter \"--number={sieve["number"]}\", so it will show '
                    f'all {SIZE} USB history entries available')

            elif sieve['number'] > SIZE:
                print_warning(
                    f'USB history has only {SIZE} entries instead of requested {sieve["number"]}, '
                    f'displaying all of them...')

            sieve['number'] = SIZE

        return [
            events_to_show[SIZE - i] for i in range(sieve['number'], 0, -1)
        ]
예제 #13
0
파일: usbevents.py 프로젝트: jumars/usbrip
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
예제 #14
0
    def create_storage(storage_type,
                       *,
                       password=None,
                       input_auth=None,
                       attributes=None,
                       compression_level='5',
                       indent=4,
                       sieve=None):
        if storage_type == 'history':
            events_to_show = _get_history_events(sieve)
        elif storage_type == 'violations':
            try:
                events_to_show = _get_violation_events(sieve, input_auth,
                                                       attributes, indent)
            except USBRipError as e:
                print_critical(str(e), initial_error=e.errors['initial_error'])
                return 1

        if events_to_show is None:
            return 1

        if events_to_show:
            min_date, max_date = _get_dates(events_to_show)
            json_file = '{}/{}-{}.json'.format(USBStorage._STORAGE_BASE,
                                               min_date, max_date)
        else:
            json_file = '{}/{}.json'.format(USBStorage._STORAGE_BASE,
                                            datetime.now().strftime('%m%d'))

        try:
            _dump_events(events_to_show, storage_type, json_file, indent)
        except USBRipError as e:
            print_critical(str(e), initial_error=e.errors['initial_error'])
            return 1

        if password is None:
            print_warning('No password provided, generating random one')
            password = _gen_random_password(12)

        storage_full_path = '{}/{}.7z'.format(USBStorage._STORAGE_BASE,
                                              storage_type)
        if os.path.exists(storage_full_path):
            os.remove(storage_full_path)

        try:
            out = _7zip_pack(storage_full_path, json_file, password,
                             compression_level)
        except USBRipError as e:
            os.remove(json_file)
            print_critical(str(e),
                           errcode=e.errors['errcode'],
                           initial_error=e.errors['initial_error'])
            return 1

        if 'Everything is Ok' in out:
            print_info('New {} storage: \'{}\''.format(storage_type,
                                                       storage_full_path))
            print_secret('Your password is', secret=password)
            os.remove(json_file)
        else:
            print_critical('Undefined behaviour while creating storage',
                           initial_error=out)