Beispiel #1
0
    def CloseStream(self):
        """Closes the file-like object.

    Returns:
      str: a return message for the report.

    Raises:
      errors.RecipeException: if the dcfldd process returns with an error.
      IOError: if CloseStream() is called before GetStream().
    """
        if not self._ddprocess:
            raise IOError('Illegal call to CloseStream() before GetStream()')

        # If there is anything still to read from the subprocess then CloseStream
        # has been called early, terminate the child process to avoid deadlock.
        c = self._ddprocess.stdout.read(1)
        if c:
            # TODO log this
            self._ddprocess.terminate()
            raise errors.RecipeException(
                'CloseStream() called but stdout still had data')

        self._ddprocess.wait()
        code = self._ddprocess.returncode
        error = self._ddprocess.stderr.read()
        if code > 0:
            raise errors.RecipeException(
                'Command dcfldd returned non-zero exit status {0:d}, with error: "{1:s}"'
                .format(code, error.decode()))
        return error
Beispiel #2
0
    def _RunCommand(self):
        """Run a command.

    Returns:
      bytes: the command output, or an error if it failed to run.
    """
        command_output = ''
        process = subprocess.Popen(self._command,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        self._logger.info('Running command \'%s\'', self._command)
        output, error = process.communicate()

        if process.returncode == 0:
            command_output = output
            self._logger.info('Command %s terminated.', self._command)
            self._logger.debug('stderr : \'%s\'', error.strip())
        else:
            command_output = (
                'Command \'{0!s}\' failed with \'{1!s}\' return code {2:d})'.
                format(self._command, error.strip(), process.returncode))
            self._logger.error(command_output)
            command_output = command_output.encode()
            raise errors.RecipeException(
                'Error running ProcessOutputArtifact command')

        return command_output
Beispiel #3
0
    def _GenerateCopyCommand(self):
        """Builds the command to run on the directory.

    Returns:
      list: the argument list for the dd command
    """
        if self._method == 'tar':
            return self._GenerateTarCopyCommand()
        else:
            raise errors.RecipeException('Unsupported method ' + self._method)
Beispiel #4
0
  def _GenerateDDCommand(self):
    """Builds the DD command to run on the disk.

    Returns:
      list: the argument list for the dd command
    """
    dd_binary = hostinfo.Which(self._DD_BINARY)
    if not dd_binary:
      raise errors.RecipeException(
          'Could not find \'{0:s}\''.format(self._DD_BINARY))
    command = [
        dd_binary, 'if={0:s}'.format(self._path),
        'hashlog={0:s}'.format(self.hashlog_filename)]
    command.extend(self._DD_OPTIONS)
    return command
Beispiel #5
0
    def GetArtifacts(self):
        """Selects the Artifacts to acquire.

    This tries to return as many Artifacts as possible even if some collection
    raised an exception.

    Returns:
      list(DiskArtifact): the artifacts corresponding to copy.

    Raises:
      errors.RecipeException: when no disk is to be collected.
    """
        artifacts = []
        disks_to_collect = []
        if getattr(self._options, 'select_disks', None):
            all_disks = self._ListDisks(all_devices=True)
            if getattr(self._options, 'no_zenity', False):
                disks_to_collect = cli.AskDiskList(all_disks)
            else:
                disks_to_collect = gui.AskDiskList(all_disks)
        elif getattr(self._options, 'disk', None):
            disks_to_collect = self._ListDisks(names=self._options.disk)
        else:
            disks_to_collect = self._ListDisks()

        if not disks_to_collect:
            raise errors.RecipeException('No disk to collect')

        disk_list_artifact = self._GetListDisksArtifact()
        artifacts.append(disk_list_artifact)

        for disk in disks_to_collect:

            hashlog_artifact = base.FileArtifact(disk.hashlog_filename)
            hashlog_artifact.remote_path = 'Disks/{0:s}'.format(
                hashlog_artifact.name)

            # It is necessary for the DiskArtifact to be appended before the
            # hashlog, as the hashlog is generated when dcfldd completes.
            disk_info_artifact = self._GetDiskInfoArtifact(disk)
            if disk_info_artifact:
                artifacts.append(disk_info_artifact)
            artifacts.append(disk)
            artifacts.append(hashlog_artifact)
        return artifacts
Beispiel #6
0
    def GetArtifacts(self):
        """Selects the Artifacts to acquire.

    This tries to return as many Artifacts as possible even if some collection
    raised an exception.

    Returns:
      list(DiskArtifact): the artifacts corresponding to copy.

    Raises:
      errors.RecipeException: when no disk is to be collected.
    """
        artifacts = []
        disks_to_collect = []
        if getattr(self._options, 'select_disks', None):
            all_disks = self._ListDisks(all_devices=True)
            disks_to_collect = gui.AskDiskList(all_disks)
        elif getattr(self._options, 'disk', None):
            disks_to_collect = self._ListDisks(names=self._options.disk)
        else:
            disks_to_collect = self._ListDisks()

        if not disks_to_collect:
            raise errors.RecipeException('No disk to collect')

        lsblk_artifact = base.StringArtifact('Disks/lsblk.txt',
                                             json.dumps(self._GetLsblkDict()))
        for disk in disks_to_collect:
            udevadm_artifact = base.StringArtifact(
                'Disks/{0:s}.udevadm.txt'.format(disk.name),
                disk.GetUdevadmProperty('udevadm_text_output'))

            hashlog_artifact = base.FileArtifact(disk.hashlog_filename)
            hashlog_artifact.remote_path = 'Disks/{0:s}'.format(
                hashlog_artifact.name)

            # It is necessary for the DiskArtifact to be appended before the
            # hashlog, as the hashlog is generated when dcfldd completes.
            artifacts.append(udevadm_artifact)
            artifacts.append(lsblk_artifact)
            artifacts.append(disk)
            artifacts.append(hashlog_artifact)
        return artifacts
Beispiel #7
0
 def GetArtifacts(self):
     raise errors.RecipeException('Everything is terrible.')
Beispiel #8
0
    def GetArtifacts(self):
        """Returns a list of DirectoryArtifacts to acquire.

    Returns:
      list(DirectoryArtifacts): the artifacts to acquire.
    """
        more_to_copy = True
        path_list = []
        while more_to_copy:
            if getattr(self._options, 'no_zenity', False):
                path = cli.AskText(
                    'Specify the path to the directory you wish to copy')
                if not os.path.isdir(path):
                    print(
                        'The following path does not exist or is not a directory:'
                        '{0:s}'.format(path))
                    continue
                path_list.append(path)
                more_to_copy = cli.Confirm(
                    'Do you wish to copy another folder?')
            else:
                path = gui.AskText(
                    'Specify the path to the directory you wish to copy')
                if not os.path.isdir(path):
                    # TODO: display an GUI error message
                    continue
                path_list.append(path)
                more_to_copy = gui.Confirm(
                    'Do you wish to copy another folder?')

        if not path_list:
            raise errors.RecipeException('No directory to collect')

        artifacts = []
        # Deduplicating paths, as they would cause the code to upload the same file
        # multiple times, which might not be allowed by the uploading process.
        for directory in list(set(path_list)):

            # 'tar' will not save some metadata such as access time. We generate
            # a 'timeline' with the find(1) command to keep this information
            timeline_artifact = None
            dir_artifact = None
            if self._platform == 'darwin':
                timeline_artifact = base.ProcessOutputArtifact([
                    'find', directory, '-exec', 'stat', '-f',
                    '0|%N|%i|%p|%u|%u|%z|%a.0|%m.0|%c.0|%B.0', '-t', '%s',
                    '{}', ';'
                ], 'Directories/{0:s}.timeline'.format(FullPathToName(path)))
                dir_artifact = MacDirectoryArtifact(
                    directory,
                    method=self._options.method,
                    compress=self._options.compress)
            elif self._platform == 'linux':
                timeline_artifact = base.ProcessOutputArtifact([
                    'find', directory, '-xdev', '-printf',
                    '0|%p|%i|%M|%U|%G|%s|%A@|%T@|%C@|0\n'
                ], 'Directores/{0:s}.timeline'.format(FullPathToName(path)))

                dir_artifact = LinuxDirectoryArtifact(
                    directory,
                    method=self._options.method,
                    compress=self._options.compress)
            else:
                raise ValueError('Unsupported platform: {0:s}'.format(
                    self._platform))

            artifacts.append(timeline_artifact)
            artifacts.append(dir_artifact)

        return artifacts
Beispiel #9
0
 def __init__(self, path, method='tar', compress=False):
     """Initializes a MacDirectoryArtifact object."""
     if method not in self._SUPPORTED_METHODS:
         raise errors.RecipeException(
             'Unsupported acquisition method on Darwin: ' + method)
     super().__init__(path, method=method, compress=compress)