def testIterateVolumes(self):
    """Test the iterate volumes functionality."""
    volume_system = gpt_volume_system.GPTVolumeSystem()

    volume_system.Open(self._gpt_path_spec)

    self.assertEqual(volume_system.number_of_volumes, 2)

    volume = volume_system.GetVolumeByIndex(0)
    self.assertIsNotNone(volume)

    self.assertEqual(volume.number_of_extents, 1)
    self.assertEqual(volume.number_of_attributes, 1)
    self.assertEqual(volume.identifier, 'p1')

    expected_value = 'b6d37ab4-051f-4556-97d2-ad1f8a609644'
    volume_attribute = volume.GetAttribute('identifier')
    self.assertIsNotNone(volume_attribute)
    self.assertEqual(volume_attribute.value, expected_value)

    volume = volume_system.GetVolumeByIndex(99)
    self.assertIsNone(volume)
Exemple #2
0
  def _GetPartitionIdentifiers(self, scan_node, options):
    """Determines the partition identifiers.

    This function determines which partition identifiers need to be scanned
    based on the volume scanner options. If no options are provided and there
    is more than a single partition the mediator is used to ask the user.

    Args:
      scan_node (SourceScanNode): scan node.
      options (VolumeScannerOptions): volume scanner options.

    Returns:
      list[str]: partition identifiers.

    Raises:
      ScannerError: if the scan node is invalid or the scanner does not know
          how to proceed.
      UserAbort: if the user requested to abort.
    """
    if not scan_node or not scan_node.path_spec:
      raise errors.ScannerError('Invalid scan node.')

    if scan_node.path_spec.type_indicator == definitions.TYPE_INDICATOR_GPT:
      volume_system = gpt_volume_system.GPTVolumeSystem()
      volume_system.Open(scan_node.path_spec)
      prefix = 'gpt'
    else:
      volume_system = tsk_volume_system.TSKVolumeSystem()
      volume_system.Open(scan_node.path_spec)
      prefix = 'p'

    volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
        volume_system)
    if not volume_identifiers:
      return []

    if options.partitions:
      if options.partitions == ['all']:
        partitions = range(1, volume_system.number_of_volumes + 1)
      else:
        partitions = options.partitions

      try:
        selected_volumes = self._NormalizedVolumeIdentifiers(
            volume_system, partitions, prefix=prefix)

        if not set(selected_volumes).difference(volume_identifiers):
          return selected_volumes
      except errors.ScannerError as exception:
        if self._mediator:
          self._mediator.PrintWarning('{0!s}'.format(exception))

    if len(volume_identifiers) > 1:
      if not self._mediator:
        raise errors.ScannerError(
            'Unable to proceed. More than one partitions found but no mediator '
            'to determine how they should be used.')

      try:
        volume_identifiers = self._mediator.GetPartitionIdentifiers(
            volume_system, volume_identifiers)

      except KeyboardInterrupt:
        raise errors.UserAbort('File system scan aborted.')

    return self._NormalizedVolumeIdentifiers(
        volume_system, volume_identifiers, prefix=prefix)
Exemple #3
0
    def _ProcessPartition(self, path_spec):
        """Generate RawDiskPartition from a PathSpec.

    Args:
      path_spec (dfvfs.PathSpec): dfVFS path spec.

    Returns:
      A new RawDiskPartition evidence item and a list of strings containing
      partition information to add to the status report.
    """
        status_report = []

        fs_path_spec = path_spec
        fs_location = None
        partition_location = None
        volume_index = None
        partition_index = None
        partition_offset = None
        partition_size = None
        lv_uuid = None

        # File system location / identifier
        is_lvm = False
        fs_location = getattr(path_spec, 'location', None)
        while path_spec.HasParent():
            type_indicator = path_spec.type_indicator
            if type_indicator == dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER:
                # APFS volume index
                volume_index = getattr(path_spec, 'volume_index', None)

            if type_indicator in (
                    dfvfs_definitions.TYPE_INDICATOR_GPT,
                    dfvfs_definitions.TYPE_INDICATOR_LVM,
                    dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION):
                if fs_location in ('\\', '/'):
                    # Partition location / identifier
                    fs_location = getattr(path_spec, 'location', None)
                partition_location = getattr(path_spec, 'location', None)
                # Partition index
                partition_index = getattr(path_spec, 'part_index', None)

                if type_indicator == dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION:
                    volume_system = tsk_volume_system.TSKVolumeSystem()
                elif type_indicator == dfvfs_definitions.TYPE_INDICATOR_LVM:
                    is_lvm = True
                    volume_system = lvm_volume_system.LVMVolumeSystem()
                else:
                    volume_system = gpt_volume_system.GPTVolumeSystem()
                try:
                    volume_system.Open(path_spec)
                    volume_identifier = partition_location.replace('/', '')
                    volume = volume_system.GetVolumeByIdentifier(
                        volume_identifier)

                    if is_lvm:
                        # LVM Logical Volume UUID
                        lv_uuid = volume.GetAttribute('identifier')
                        if lv_uuid:
                            lv_uuid = lv_uuid.value

                    partition_offset = volume.extents[0].offset
                    partition_size = volume.extents[0].size
                except dfvfs_errors.VolumeSystemError as e:
                    raise TurbiniaException(
                        'Could not process partition: {0!s}'.format(e))
                break

            path_spec = path_spec.parent

        status_report.append(fmt.heading5('{0!s}:'.format(fs_location)))
        status_report.append(
            fmt.bullet('Filesystem: {0!s}'.format(
                fs_path_spec.type_indicator)))
        if volume_index is not None:
            status_report.append(
                fmt.bullet('Volume index: {0!s}'.format(volume_index)))
        if partition_index is not None:
            status_report.append(
                fmt.bullet('Partition index: {0!s}'.format(partition_index)))
            status_report.append(
                fmt.bullet('Partition offset: {0!s}'.format(partition_offset)))
            status_report.append(
                fmt.bullet('Partition size: {0!s}'.format(partition_size)))
        if volume_index is None and partition_index is None:
            status_report.append(
                fmt.bullet('Source evidence is a volume image'))

        # Not setting path_spec here as it will need to be generated for each task
        partition_evidence = DiskPartition(partition_location=fs_location,
                                           partition_offset=partition_offset,
                                           partition_size=partition_size,
                                           lv_uuid=lv_uuid)

        return partition_evidence, status_report
Exemple #4
0
  def _GetTSKPartitionIdentifiers(self, scan_node):
    """Determines the TSK partition identifiers.

    This method first checks for the preferred partition number, then
    falls back to prompt the user if no usable preferences were specified.

    Args:
      scan_node (dfvfs.SourceScanNode): scan node.

    Returns:
      list[str]: TSK partition identifiers.

    Raises:
      RuntimeError: if the volume for a specific identifier cannot be
          retrieved.
      SourceScannerError: if the scan node is invalid or more than 1 volume
          was found but no volumes were specified.
      UserAbort: if the user requested to abort.
    """
    if not scan_node or not scan_node.path_spec:
      raise errors.SourceScannerError('Invalid scan node.')

    if scan_node.path_spec.type_indicator == (
        dfvfs_definitions.TYPE_INDICATOR_GPT):
      volume_system = gpt_volume_system.GPTVolumeSystem()
    else:
      volume_system = tsk_volume_system.TSKVolumeSystem()

    volume_system.Open(scan_node.path_spec)

    volume_identifiers = self._source_scanner.GetVolumeIdentifiers(
        volume_system)
    if not volume_identifiers:
      return []

    # TODO: refactor self._partitions to use scan options.
    if self._partitions:
      if self._partitions == 'all':
        partitions = volume_system.volume_identifiers
      else:
        partitions = self._mediator.ParseVolumeIdentifiersString(
            self._partitions, prefix='p')

      selected_volume_identifiers = self._NormalizedVolumeIdentifiers(
          volume_system, partitions, prefix='p')

      if not set(selected_volume_identifiers).difference(volume_identifiers):
        return selected_volume_identifiers

    if len(volume_identifiers) > 1:
      if self._unattended_mode:
        raise errors.SourceScannerError(
            'More than 1 partition found but no partitions specified.')

      try:
        volume_identifiers = self._mediator.GetPartitionIdentifiers(
            volume_system, volume_identifiers)
      except KeyboardInterrupt:
        raise errors.UserAbort('File system scan aborted.')

    return self._NormalizedVolumeIdentifiers(
        volume_system, volume_identifiers, prefix='p')
Exemple #5
0
    def _ProcessPartition(self, path_spec):
        """Generate RawDiskPartition from a PathSpec.

    Args:
      path_spec (dfvfs.PathSpec): dfVFS path spec.

    Returns:
      A new RawDiskPartition evidence item and a list of strings containing
      partition information to add to the status report.
    """
        status_report = []

        fs_path_spec = path_spec
        fs_location = None
        partition_location = None
        volume_index = None
        partition_index = None
        partition_offset = None
        partition_size = None

        # File system location / identifier
        fs_location = getattr(path_spec, 'location', None)
        while path_spec.HasParent():
            type_indicator = path_spec.type_indicator
            if type_indicator == dfvfs_definitions.TYPE_INDICATOR_APFS_CONTAINER:
                # APFS volume index
                volume_index = getattr(path_spec, 'volume_index', None)

            if type_indicator in (
                    dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION,
                    dfvfs_definitions.TYPE_INDICATOR_GPT):
                if fs_location in ('\\', '/'):
                    # Partition location / identifier
                    fs_location = getattr(path_spec, 'location', None)
                partition_location = getattr(path_spec, 'location', None)
                # Partition index
                partition_index = getattr(path_spec, 'part_index', None)

                if type_indicator == dfvfs_definitions.TYPE_INDICATOR_TSK_PARTITION:
                    volume_system = tsk_volume_system.TSKVolumeSystem()
                else:
                    volume_system = gpt_volume_system.GPTVolumeSystem()
                try:
                    volume_system.Open(path_spec)
                    volume_identifier = partition_location.replace('/', '')
                    volume = volume_system.GetVolumeByIdentifier(
                        volume_identifier)

                    partition_offset = volume.extents[0].offset
                    partition_size = volume.extents[0].size
                except dfvfs_errors.VolumeSystemError as e:
                    raise TurbiniaException(
                        'Could not process partition: {0!s}'.format(e))
                break

            path_spec = path_spec.parent

        status_report.append(fmt.heading5('{0!s}:'.format(fs_location)))
        if partition_index:
            if not volume_index is None:
                status_report.append(
                    fmt.bullet('Volume index: {0!s}'.format(volume_index)))
            status_report.append(
                fmt.bullet('Partition index: {0!s}'.format(partition_index)))
            status_report.append(
                fmt.bullet('Partition offset: {0!s}'.format(partition_offset)))
            status_report.append(
                fmt.bullet('Partition size: {0!s}'.format(partition_size)))
        else:
            status_report.append(
                fmt.bullet('Source evidence is a volume image'))

        partition_evidence = DiskPartition(path_spec=fs_path_spec,
                                           partition_offset=partition_offset,
                                           partition_size=partition_size)

        return partition_evidence, status_report