Ejemplo n.º 1
0
    def _RunAndWaitForVFSFileUpdate(self, path):
        """Runs a flow on the client, and waits for it to finish."""

        client_id = rdf_client.GetClientURNFromPath(path)

        # If we're not actually in a directory on a client, no need to run a flow.
        if client_id is None:
            return

        flow_utils.UpdateVFSFileAndWait(client_id,
                                        token=self.token,
                                        vfs_file_urn=self.root.Add(path),
                                        timeout=self.timeout)
Ejemplo n.º 2
0
    def Read(self, path, length=None, offset=0, fh=None):
        fd = aff4.FACTORY.Open(self.root.Add(path), token=self.token)
        last = fd.Get(fd.Schema.CONTENT_LAST)
        client_id = rdf_client.GetClientURNFromPath(path)

        if not self.DataRefreshRequired(last=last, path=path):
            return super(GRRFuse, self).Read(path, length, offset, fh)

        if isinstance(fd, standard.AFF4SparseImage):
            # If we have a sparse image, update just a part of it.
            self.UpdateSparseImageIfNeeded(fd, length, offset)
            # Read the file from the datastore as usual.
            return super(GRRFuse, self).Read(path, length, offset, fh)

        # If it's the first time we've seen this path (or we're asking
        # explicitly), try and make it an AFF4SparseImage.
        if last is None or self.force_sparse_image:
            pathspec = fd.Get(fd.Schema.PATHSPEC)

            # Either makes a new AFF4SparseImage or gets the file fully,
            # depending on size.
            flow_utils.StartFlowAndWait(
                client_id,
                token=self.token,
                flow_name=filesystem.MakeNewAFF4SparseImage.__name__,
                pathspec=pathspec,
                size_threshold=self.size_threshold)

            # Reopen the fd in case it's changed to be an AFF4SparseImage
            fd = aff4.FACTORY.Open(self.root.Add(path), token=self.token)
            # If we are now a sparse image, just download the part we requested
            # from the client.
            if isinstance(fd, standard.AFF4SparseImage):
                flow_utils.StartFlowAndWait(
                    client_id,
                    token=self.token,
                    flow_name=filesystem.FetchBufferForSparseImage.__name__,
                    file_urn=self.root.Add(path),
                    length=length,
                    offset=offset)
        else:
            # This was a file we'd seen before that wasn't a sparse image, so update
            # it the usual way.
            self._RunAndWaitForVFSFileUpdate(path)

        # Read the file from the datastore as usual.
        return super(GRRFuse, self).Read(path, length, offset, fh)
    def Run(self, args):
        """Downloads files/directories with the given path."""

        # If we're exporting a path inside a client, check to see if we have access
        # to that client and get the appropriate token.  This means we can avoid
        # having to specify --reason.
        client_id = client.GetClientURNFromPath(args.path)

        if client_id is not None:
            token = security.Approval.GetApprovalForObject(
                client_id,
                token=data_store.default_token,
                username=data_store.default_token.username)
            data_store.default_token = token

        try:
            directory = aff4.FACTORY.Open(args.path,
                                          "AFF4Volume",
                                          token=data_store.default_token)
        except aff4.InstantiationError:
            directory = None

        if directory and not isinstance(directory, aff4.VFSDirectory):
            # If directory is not a VFSDirectory, check that it's in its' parent
            # children list. This way we check that the path actually exists.
            directory_parent = aff4.FACTORY.Open(
                directory.urn.Dirname(), token=data_store.default_token)
            if directory.urn not in directory_parent.ListChildren():
                raise RuntimeError("Specified path %s doesn't exist!" %
                                   directory.urn)

        if directory:
            export_utils.RecursiveDownload(directory,
                                           args.output,
                                           overwrite=args.overwrite,
                                           max_depth=args.depth,
                                           max_threads=args.threads)
        else:
            export_utils.CopyAFF4ToLocal(args.path,
                                         args.output,
                                         overwrite=args.overwrite,
                                         token=data_store.default_token)
Ejemplo n.º 4
0
def main(unused_argv):
  config_lib.CONFIG.AddContext(
      "Commandline Context",
      "Context applied for all command line tools")
  startup.Init()

  if fuse is None:
    logging.critical("""Could not start!
fusepy must be installed to run fuse_mount.py!
Try:
  sudo pip install fusepy""")
    sys.exit(1)

  if not flags.FLAGS.mountpoint:
    Usage()
    sys.exit(1)

  # We multiple inherit from GRRFuse and fuse.Operations. In the
  # case that fuse is present, we run the actual FUSE layer, since we have
  # fuse.Operations. In the case that fuse is not present, we have already
  # exited by now if we were run from the command line, and if we were not run
  # from the command line, we've been imported, and we run the tests using a
  # mock fuse.

  class FuseOperation(GRRFuse, fuse.Operations):
    pass

  root = flags.FLAGS.aff4path

  username = flags.FLAGS.username or getpass.getuser()
  token = access_control.ACLToken(username=username,
                                  reason=flags.FLAGS.reason or "fusemount")

  # If we're exporting a path inside a client, check to see if we have access to
  # that client and get the appropriate token.
  client_id = client.GetClientURNFromPath(root)
  if client_id is not None:
    token = security.Approval.GetApprovalForObject(
        client_id,
        token=token,
        username=username)

  data_store.default_token = token

  logging.info("fuse_mount.py is mounting %s at %s....", root,
               flags.FLAGS.mountpoint)

  refresh_policy = flags.FLAGS.refresh_policy

  if refresh_policy == "always":
    max_age_before_refresh = datetime.timedelta(0)
  elif refresh_policy == "never":
    # Set the max age to be the maximum possible time difference.
    max_age_before_refresh = datetime.timedelta.max
  elif refresh_policy == "if_older_than_max_age":
    max_age_before_refresh = datetime.timedelta(
        seconds=flags.FLAGS.max_age_before_refresh)
  else:
    # Otherwise, a flag outside the enum was given and the flag validator threw
    # an execption.
    pass

  fuse_operation = FuseOperation(
      root=root,
      token=token,
      max_age_before_refresh=max_age_before_refresh,
      ignore_cache=flags.FLAGS.ignore_cache,
      force_sparse_image=flags.FLAGS.force_sparse_image,
      sparse_image_threshold=flags.FLAGS.sparse_image_threshold,
      timeout=flags.FLAGS.timeout)

  fuse.FUSE(fuse_operation, flags.FLAGS.mountpoint,
            foreground=not flags.FLAGS.background)