OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """The storage media CLI tool.""" | 2 """The storage media CLI tool.""" |
3 | 3 |
4 import getpass | 4 import getpass |
5 import logging | 5 import logging |
6 import os | 6 import os |
7 import sys | 7 import sys |
8 | 8 |
9 from dfdatetime import filetime as dfdatetime_filetime | 9 from dfdatetime import filetime as dfdatetime_filetime |
10 from dfvfs.analyzer import analyzer as dfvfs_analyzer | 10 from dfvfs.analyzer import analyzer as dfvfs_analyzer |
(...skipping 19 matching lines...) Expand all Loading... |
30 fvde_analyzer_helper.FVDEAnalyzerHelper()) | 30 fvde_analyzer_helper.FVDEAnalyzerHelper()) |
31 except KeyError: | 31 except KeyError: |
32 pass | 32 pass |
33 | 33 |
34 | 34 |
35 class StorageMediaTool(tools.CLITool): | 35 class StorageMediaTool(tools.CLITool): |
36 """Class that implements a storage media CLI tool.""" | 36 """Class that implements a storage media CLI tool.""" |
37 | 37 |
38 _DEFAULT_BYTES_PER_SECTOR = 512 | 38 _DEFAULT_BYTES_PER_SECTOR = 512 |
39 | 39 |
| 40 # TODO: remove this redirect. |
40 _SOURCE_OPTION = u'source' | 41 _SOURCE_OPTION = u'source' |
41 | 42 |
42 _BINARY_DATA_CREDENTIAL_TYPES = [u'key_data'] | 43 _BINARY_DATA_CREDENTIAL_TYPES = [u'key_data'] |
43 | 44 |
44 _SUPPORTED_CREDENTIAL_TYPES = [ | 45 _SUPPORTED_CREDENTIAL_TYPES = [ |
45 u'key_data', u'password', u'recovery_password', u'startup_key'] | 46 u'key_data', u'password', u'recovery_password', u'startup_key'] |
46 | 47 |
47 # For context see: http://en.wikipedia.org/wiki/Byte | 48 # For context see: http://en.wikipedia.org/wiki/Byte |
48 _UNITS_1000 = [u'B', u'kB', u'MB', u'GB', u'TB', u'EB', u'ZB', u'YB'] | 49 _UNITS_1000 = [u'B', u'kB', u'MB', u'GB', u'TB', u'EB', u'ZB', u'YB'] |
49 _UNITS_1024 = [u'B', u'KiB', u'MiB', u'GiB', u'TiB', u'EiB', u'ZiB', u'YiB'] | 50 _UNITS_1024 = [u'B', u'KiB', u'MiB', u'GiB', u'TiB', u'EiB', u'ZiB', u'YiB'] |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 if credential_type in self._BINARY_DATA_CREDENTIAL_TYPES: | 308 if credential_type in self._BINARY_DATA_CREDENTIAL_TYPES: |
308 try: | 309 try: |
309 credential_data = credential_data.decode(u'hex') | 310 credential_data = credential_data.decode(u'hex') |
310 except TypeError: | 311 except TypeError: |
311 raise errors.BadConfigOption( | 312 raise errors.BadConfigOption( |
312 u'Unsupported credential data for: {0:s}.'.format( | 313 u'Unsupported credential data for: {0:s}.'.format( |
313 credential_string)) | 314 credential_string)) |
314 | 315 |
315 self._credentials.append((credential_type, credential_data)) | 316 self._credentials.append((credential_type, credential_data)) |
316 | 317 |
317 def _ParseFilterOptions(self, options): | |
318 """Parses the filter options. | |
319 | |
320 Args: | |
321 options (argparse.Namespace): command line arguments. | |
322 | |
323 Raises: | |
324 BadConfigOption: if the options are invalid. | |
325 """ | |
326 filter_file = self.ParseStringOption(options, u'file_filter') | |
327 if not filter_file: | |
328 return | |
329 | |
330 if self._data_location: | |
331 filter_file_base = os.path.basename(filter_file) | |
332 filter_file_check = os.path.join(self._data_location, filter_file_base) | |
333 if os.path.isfile(filter_file_check): | |
334 self._filter_file = filter_file_check | |
335 return | |
336 | |
337 if not os.path.isfile(filter_file): | |
338 raise errors.BadConfigOption( | |
339 u'No such collection filter file: {0:s}.'.format(filter_file)) | |
340 | |
341 self._filter_file = filter_file | |
342 | |
343 def _ParsePartitionsString(self, partitions): | 318 def _ParsePartitionsString(self, partitions): |
344 """Parses the user specified partitions string. | 319 """Parses the user specified partitions string. |
345 | 320 |
346 Args: | 321 Args: |
347 partitions (str): partitions. A range of partitions can be defined | 322 partitions (str): partitions. A range of partitions can be defined |
348 as: "3..5". Multiple partitions can be defined as: "1,3,5" (a list | 323 as: "3..5". Multiple partitions can be defined as: "1,3,5" (a list |
349 of comma separated values). Ranges and lists can also be combined | 324 of comma separated values). Ranges and lists can also be combined |
350 as: "1,3..5". The first partition is 1. All partition can be | 325 as: "1,3..5". The first partition is 1. All partition can be |
351 defined as: "all". | 326 defined as: "all". |
352 | 327 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 partition_number = int(partition_range, 10) | 361 partition_number = int(partition_range, 10) |
387 except ValueError: | 362 except ValueError: |
388 raise errors.BadConfigOption( | 363 raise errors.BadConfigOption( |
389 u'Invalid partition range: {0:s}.'.format(partition_range)) | 364 u'Invalid partition range: {0:s}.'.format(partition_range)) |
390 | 365 |
391 if partition_number not in partition_numbers: | 366 if partition_number not in partition_numbers: |
392 partition_numbers.append(partition_number) | 367 partition_numbers.append(partition_number) |
393 | 368 |
394 return sorted(partition_numbers) | 369 return sorted(partition_numbers) |
395 | 370 |
| 371 def _ParseSourcePathOption(self, options): |
| 372 """Parses the source path option. |
| 373 |
| 374 Args: |
| 375 options (argparse.Namespace): command line arguments. |
| 376 |
| 377 Raises: |
| 378 BadConfigOption: if the options are invalid. |
| 379 """ |
| 380 self._source_path = self.ParseStringOption(options, self._SOURCE_OPTION) |
| 381 if not self._source_path: |
| 382 raise errors.BadConfigOption(u'Missing source path.') |
| 383 |
| 384 self._source_path = os.path.abspath(self._source_path) |
| 385 |
| 386 def _ParseStorageMediaOptions(self, options): |
| 387 """Parses the storage media options. |
| 388 |
| 389 Args: |
| 390 options (argparse.Namespace): command line arguments. |
| 391 |
| 392 Raises: |
| 393 BadConfigOption: if the options are invalid. |
| 394 """ |
| 395 self._ParseStorageMediaImageOptions(options) |
| 396 self._ParseVSSProcessingOptions(options) |
| 397 self._ParseCredentialOptions(options) |
| 398 self._ParseSourcePathOption(options) |
| 399 |
396 def _ParseStorageMediaImageOptions(self, options): | 400 def _ParseStorageMediaImageOptions(self, options): |
397 """Parses the storage media image options. | 401 """Parses the storage media image options. |
398 | 402 |
399 Args: | 403 Args: |
400 options (argparse.Namespace): command line arguments. | 404 options (argparse.Namespace): command line arguments. |
401 | 405 |
402 Raises: | 406 Raises: |
403 BadConfigOption: if the options are invalid. | 407 BadConfigOption: if the options are invalid. |
404 """ | 408 """ |
405 partitions = getattr(options, u'partitions', None) | 409 partitions = getattr(options, u'partitions', None) |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 u'--credential', action=u'append', default=[], type=str, | 976 u'--credential', action=u'append', default=[], type=str, |
973 dest=u'credentials', metavar=u'TYPE:DATA', help=( | 977 dest=u'credentials', metavar=u'TYPE:DATA', help=( |
974 u'Define a credentials that can be used to unlock encrypted ' | 978 u'Define a credentials that can be used to unlock encrypted ' |
975 u'volumes e.g. BitLocker. The credential is defined as type:data ' | 979 u'volumes e.g. BitLocker. The credential is defined as type:data ' |
976 u'e.g. "password:BDE-test". Supported credential types are: ' | 980 u'e.g. "password:BDE-test". Supported credential types are: ' |
977 u'{0:s}. Binary key data is expected to be passed in BASE-16 ' | 981 u'{0:s}. Binary key data is expected to be passed in BASE-16 ' |
978 u'encoding (hexadecimal). WARNING credentials passed via command ' | 982 u'encoding (hexadecimal). WARNING credentials passed via command ' |
979 u'line arguments can end up in logs, so use this option with ' | 983 u'line arguments can end up in logs, so use this option with ' |
980 u'care.').format(u', '.join(self._SUPPORTED_CREDENTIAL_TYPES))) | 984 u'care.').format(u', '.join(self._SUPPORTED_CREDENTIAL_TYPES))) |
981 | 985 |
982 def AddFilterOptions(self, argument_group): | |
983 """Adds the filter options to the argument group. | |
984 | |
985 Args: | |
986 argument_group (argparse._ArgumentGroup): argparse argument group. | |
987 """ | |
988 argument_group.add_argument( | |
989 u'-f', u'--file_filter', u'--file-filter', dest=u'file_filter', | |
990 action=u'store', type=str, default=None, help=( | |
991 u'List of files to include for targeted collection of files to ' | |
992 u'parse, one line per file path, setup is /path|file - where each ' | |
993 u'element can contain either a variable set in the preprocessing ' | |
994 u'stage or a regular expression.')) | |
995 | |
996 def AddStorageMediaImageOptions(self, argument_group): | 986 def AddStorageMediaImageOptions(self, argument_group): |
997 """Adds the storage media image options to the argument group. | 987 """Adds the storage media image options to the argument group. |
998 | 988 |
999 Args: | 989 Args: |
1000 argument_group (argparse._ArgumentGroup): argparse argument group. | 990 argument_group (argparse._ArgumentGroup): argparse argument group. |
1001 """ | 991 """ |
1002 argument_group.add_argument( | 992 argument_group.add_argument( |
1003 u'--partition', dest=u'partition', action=u'store', type=str, | 993 u'--partition', dest=u'partition', action=u'store', type=str, |
1004 default=None, help=( | 994 default=None, help=( |
1005 u'Choose a partition number from a disk image. This partition ' | 995 u'Choose a partition number from a disk image. This partition ' |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 argument_group.add_argument( | 1049 argument_group.add_argument( |
1060 u'--vss_stores', u'--vss-stores', dest=u'vss_stores', action=u'store', | 1050 u'--vss_stores', u'--vss-stores', dest=u'vss_stores', action=u'store', |
1061 type=str, default=None, help=( | 1051 type=str, default=None, help=( |
1062 u'Define Volume Shadow Snapshots (VSS) (or stores that need to be ' | 1052 u'Define Volume Shadow Snapshots (VSS) (or stores that need to be ' |
1063 u'processed. A range of stores can be defined as: "3..5". ' | 1053 u'processed. A range of stores can be defined as: "3..5". ' |
1064 u'Multiple stores can be defined as: "1,3,5" (a list of comma ' | 1054 u'Multiple stores can be defined as: "1,3,5" (a list of comma ' |
1065 u'separated values). Ranges and lists can also be combined as: ' | 1055 u'separated values). Ranges and lists can also be combined as: ' |
1066 u'"1,3..5". The first store is 1. All stores can be defined as: ' | 1056 u'"1,3..5". The first store is 1. All stores can be defined as: ' |
1067 u'"all".')) | 1057 u'"all".')) |
1068 | 1058 |
1069 def ParseOptions(self, options): | |
1070 """Parses tool specific options. | |
1071 | |
1072 Args: | |
1073 options (argparse.Namespace): command line arguments. | |
1074 | |
1075 Raises: | |
1076 BadConfigOption: if the options are invalid. | |
1077 """ | |
1078 super(StorageMediaTool, self).ParseOptions(options) | |
1079 self._ParseStorageMediaImageOptions(options) | |
1080 self._ParseVSSProcessingOptions(options) | |
1081 self._ParseCredentialOptions(options) | |
1082 | |
1083 self._source_path = self.ParseStringOption(options, self._SOURCE_OPTION) | |
1084 if not self._source_path: | |
1085 raise errors.BadConfigOption(u'Missing source path.') | |
1086 | |
1087 self._source_path = os.path.abspath(self._source_path) | |
1088 | |
1089 def ScanSource(self): | 1059 def ScanSource(self): |
1090 """Scans the source path for volume and file systems. | 1060 """Scans the source path for volume and file systems. |
1091 | 1061 |
1092 This function sets the internal source path specification and source | 1062 This function sets the internal source path specification and source |
1093 type values. | 1063 type values. |
1094 | 1064 |
1095 Returns: | 1065 Returns: |
1096 dfvfs.SourceScannerContext: source scanner context. | 1066 dfvfs.SourceScannerContext: source scanner context. |
1097 | 1067 |
1098 Raises: | 1068 Raises: |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 for partition_identifier in partition_identifiers: | 1114 for partition_identifier in partition_identifiers: |
1145 location = u'/{0:s}'.format(partition_identifier) | 1115 location = u'/{0:s}'.format(partition_identifier) |
1146 sub_scan_node = scan_node.GetSubNodeByLocation(location) | 1116 sub_scan_node = scan_node.GetSubNodeByLocation(location) |
1147 self._ScanVolume(scan_context, sub_scan_node) | 1117 self._ScanVolume(scan_context, sub_scan_node) |
1148 | 1118 |
1149 if not self._source_path_specs: | 1119 if not self._source_path_specs: |
1150 raise errors.SourceScannerError( | 1120 raise errors.SourceScannerError( |
1151 u'No supported file system found in source.') | 1121 u'No supported file system found in source.') |
1152 | 1122 |
1153 return scan_context | 1123 return scan_context |
OLD | NEW |