Exemple #1
0
    def GetRegistryValue(self, source):
        """Retrieve directly specified registry values, returning Stat objects."""
        new_paths = set()
        has_glob = False
        for kvdict in source.attributes["key_value_pairs"]:
            if "*" in kvdict["key"] or paths.GROUPING_PATTERN.search(
                    kvdict["key"]):
                has_glob = True

            if kvdict["value"]:
                # This currently only supports key value pairs specified using forward
                # slash.
                path = "\\".join((kvdict["key"], kvdict["value"]))
            else:
                # If value is not set, we want to get the default value. In
                # GRR this is done by specifying the key only, so this is what
                # we do here.
                path = kvdict["key"]

            expanded_paths = artifact_utils.InterpolateKbAttributes(
                path,
                self.state.knowledge_base,
                ignore_errors=self.args.ignore_interpolation_errors)
            new_paths.update(expanded_paths)

        if has_glob:
            self.CallFlow(filesystem.Glob.__name__,
                          paths=new_paths,
                          pathtype=paths.PathSpec.PathType.REGISTRY,
                          request_data={
                              "artifact_name": self.current_artifact_name,
                              "source": source.ToPrimitiveDict()
                          },
                          next_state="ProcessCollected")
        else:
            # We call statfile directly for keys that don't include globs because it
            # is faster and some artifacts rely on getting an IOError to trigger
            # fallback processing.
            for new_path in new_paths:
                pathspec = paths.PathSpec(
                    path=new_path, pathtype=paths.PathSpec.PathType.REGISTRY)

                # TODO(hanuszczak): Support for old clients ends on 2021-01-01.
                # This conditional should be removed after that date.
                if self.client_version >= 3221:
                    stub = server_stubs.GetFileStat
                    request = rdf_client.GetFileStatRequest(pathspec=pathspec)
                else:
                    stub = server_stubs.StatFile
                    request = rdf_client.ListDirRequest(pathspec=pathspec)

                self.CallClient(stub,
                                request,
                                request_data={
                                    "artifact_name":
                                    self.current_artifact_name,
                                    "source": source.ToPrimitiveDict()
                                },
                                next_state="ProcessCollectedRegistryStatEntry")
Exemple #2
0
  def Start(self):
    # TODO(hanuszczak): Support for old clients ends on 2021-01-01.
    # This conditional should be removed after that date.
    if self.client_version >= 3221:
      stub = server_stubs.GetFileStat
      request = rdf_client.GetFileStatRequest(pathspec=self.args.pathspec)
    else:
      stub = server_stubs.StatFile
      request = rdf_client.ListDirRequest(pathspec=self.args.pathspec)

    self.CallClient(stub, request, next_state="ProcessStat")
Exemple #3
0
    def testStatSize(self):
        with test_lib.AutoTempFilePath() as temp_filepath:
            with open(temp_filepath, "wb") as temp_file:
                temp_file.write("123456")

            pathspec = rdf_paths.PathSpec(
                path=temp_filepath, pathtype=rdf_paths.PathSpec.PathType.OS)

            request = rdf_client.GetFileStatRequest(pathspec=pathspec)
            results = self.RunAction(standard.GetFileStat, request)

            self.assertEqual(len(results), 1)
            self.assertEqual(results[0].st_size, 6)
Exemple #4
0
    def _TryToStartNextPathspec(self):
        """Try to schedule the next pathspec if there is enough capacity."""
        # Nothing to do here.
        if self.state.maximum_pending_files <= len(self.state.pending_files):
            return

        if self.state.maximum_pending_files <= len(self.state.pending_hashes):
            return

        try:
            index = self.state.next_pathspec_to_start
            pathspec = self.state.indexed_pathspecs[index]
            self.state.next_pathspec_to_start = index + 1
        except IndexError:
            # We did all the pathspecs, nothing left to do here.
            return

        # Add the file tracker to the pending hashes list where it waits until the
        # hash comes back.
        self.state.pending_hashes[index] = {"index": index}

        # First state the file, then hash the file.

        # TODO(hanuszczak): Support for old clients ends on 2021-01-01.
        # This conditional should be removed after that date.
        if self.client_version >= 3221:
            stub = server_stubs.GetFileStat
            request = rdf_client.GetFileStatRequest(pathspec=pathspec)
        else:
            stub = server_stubs.StatFile
            request = rdf_client.ListDirRequest(pathspec=pathspec)

        self.CallClient(stub,
                        request,
                        next_state="StoreStat",
                        request_data=dict(index=index))

        request = rdf_client.FingerprintRequest(
            pathspec=pathspec, max_filesize=self.state.file_size)
        request.AddRequest(
            fp_type=rdf_client.FingerprintTuple.Type.FPT_GENERIC,
            hashers=[
                rdf_client.FingerprintTuple.HashType.MD5,
                rdf_client.FingerprintTuple.HashType.SHA1,
                rdf_client.FingerprintTuple.HashType.SHA256
            ])

        self.CallClient(server_stubs.HashFile,
                        request,
                        next_state="ReceiveFileHash",
                        request_data=dict(index=index))
Exemple #5
0
    def testStatExtAttrsDisabled(self):
        with test_lib.AutoTempFilePath() as temp_filepath:
            client_test_lib.SetExtAttr(temp_filepath,
                                       name="user.foo",
                                       value="bar")

            pathspec = rdf_paths.PathSpec(
                path=temp_filepath, pathtype=rdf_paths.PathSpec.PathType.OS)

            request = rdf_client.GetFileStatRequest(pathspec=pathspec,
                                                    collect_ext_attrs=False)
            results = self.RunAction(standard.GetFileStat, request)

            self.assertEqual(len(results), 1)
            self.assertEqual(len(results[0].ext_attrs), 0)
Exemple #6
0
    def testStatExtAttrsDisabled(self):
        with test_lib.AutoTempFilePath() as temp_filepath:
            # TODO(hanuszczak): See a TODO comment above.
            if subprocess.call(["which", "setfattr"]) != 0:
                raise unittest.SkipTest("`setfattr` command is not available")
            if subprocess.call([
                    "setfattr", temp_filepath, "-n", "user.foo", "-v", "bar"
            ]) != 0:
                raise unittest.SkipTest("extended attributes not supported")

            pathspec = rdf_paths.PathSpec(
                path=temp_filepath, pathtype=rdf_paths.PathSpec.PathType.OS)

            request = rdf_client.GetFileStatRequest(pathspec=pathspec,
                                                    collect_ext_attrs=False)
            results = self.RunAction(standard.GetFileStat, request)

            self.assertEqual(len(results), 1)
            self.assertEqual(len(results[0].ext_attrs), 0)
Exemple #7
0
  def Start(self):
    """Issue a request to list the directory."""
    self.state.urn = None

    # TODO(hanuszczak): Support for old clients ends on 2021-01-01.
    # This conditional should be removed after that date.
    if self.client_version >= 3221:
      stub = server_stubs.GetFileStat
      request = rdf_client.GetFileStatRequest(pathspec=self.args.pathspec)
    else:
      stub = server_stubs.StatFile
      request = rdf_client.ListDirRequest(pathspec=self.args.pathspec)

    self.CallClient(stub, request, next_state="Stat")

    # We use data to pass the path to the callback:
    self.CallClient(
        server_stubs.ListDirectory,
        pathspec=self.args.pathspec,
        next_state="List")
Exemple #8
0
    def Start(self):
        """Get information about the file from the client."""
        self.state.max_chunk_number = max(
            2, self.args.read_length / self.CHUNK_SIZE)

        self.state.current_chunk_number = 0
        self.state.file_size = 0
        self.state.blobs = []
        self.state.stat_entry = None

        # TODO(hanuszczak): Support for old clients ends on 2021-01-01.
        # This conditional should be removed after that date.
        if self.client_version >= 3221:
            stub = server_stubs.GetFileStat
            request = rdf_client.GetFileStatRequest(
                pathspec=self.args.pathspec)
        else:
            stub = server_stubs.StatFile
            request = rdf_client.ListDirRequest(pathspec=self.args.pathspec)

        self.CallClient(stub, request, next_state="Stat")
Exemple #9
0
    def testStatExtAttrsEnabled(self):
        with test_lib.AutoTempFilePath() as temp_filepath:
            # TODO(hanuszczak): This call is repeated in many tests and should be
            # refactored to some utility method in testing library.
            if subprocess.call(["which", "setfattr"]) != 0:
                raise unittest.SkipTest("`setfattr` command is not available")
            if subprocess.call([
                    "setfattr", temp_filepath, "-n", "user.foo", "-v", "bar"
            ]) != 0:
                raise unittest.SkipTest("extended attributes not supported")

            pathspec = rdf_paths.PathSpec(
                path=temp_filepath, pathtype=rdf_paths.PathSpec.PathType.OS)

            request = rdf_client.GetFileStatRequest(pathspec=pathspec,
                                                    collect_ext_attrs=True)
            results = self.RunAction(standard.GetFileStat, request)

            self.assertEqual(len(results), 1)
            self.assertEqual(len(results[0].ext_attrs), 1)
            self.assertEqual(results[0].ext_attrs[0].name, "user.foo")
            self.assertEqual(results[0].ext_attrs[0].value, "bar")
Exemple #10
0
  def _ProcessResponse(self, response, component_paths, base_wildcard=False):
    for component_path in component_paths:
      regexes_to_get = []
      recursions_to_get = {}

      node = self.FindNode(component_path)

      if not node:
        # Node is empty representing a leaf node - we found a hit - report it.
        self.GlobReportMatch(response)
        return

      # There are further components in the tree - iterate over them.
      for component_str, next_node in node.items():
        component = rdf_paths.PathSpec.FromSerializedString(component_str)
        next_component = component_path + [component_str]

        # If we reach this point, we are instructed to go deeper into the
        # directory structure. We only want to actually do this if
        # - the last response was a proper directory,
        # - or it was a file (an image) that was explicitly given meaning
        #   no wildcards or groupings,
        # - or process_non_regular_files was set.
        #
        # This reduces the number of TSK opens on the client that may
        # sometimes lead to instabilities due to bugs in the library.

        if response and (not (stat.S_ISDIR(response.st_mode) or
                              not base_wildcard or
                              self.state.process_non_regular_files)):
          continue

        if component.path_options == component.Options.RECURSIVE:
          recursions_to_get.setdefault(component.recursion_depth,
                                       []).append(component)
        elif component.path_options == component.Options.REGEX:
          regexes_to_get.append(component)

        elif component.path_options == component.Options.CASE_INSENSITIVE:
          # Here we need to create the next pathspec by appending the current
          # component to what we already have. If we don't have anything yet, we
          # fall back to the root path. If there is no root path either, the
          # current component becomes the new base.
          base_pathspec = self._GetBasePathspec(response)
          if base_pathspec:
            pathspec = base_pathspec.Append(component)
          else:
            pathspec = component

          if not next_node:
            # Check for the existence of the last node.
            if (response is None or (response and
                                     (response.st_mode == 0 or
                                      not stat.S_ISREG(response.st_mode)))):
              # If next node is empty, this node is a leaf node, we therefore
              # must stat it to check that it is there. There is a special case
              # here where this pathspec points to a file/directory in the root
              # directory. In this case, response will be None but we still need
              # to stat it.

              # TODO(hanuszczak): Support for old clients ends on 2021-01-01.
              # This conditional should be removed after that date.
              if self.client_version >= 3221:
                stub = server_stubs.GetFileStat
                request = rdf_client.GetFileStatRequest(
                    pathspec=pathspec,
                    collect_ext_attrs=self.state.collect_ext_attrs)
              else:
                stub = server_stubs.StatFile
                request = rdf_client.ListDirRequest(pathspec=pathspec)

              self.CallClient(
                  stub,
                  request,
                  next_state="ProcessEntry",
                  request_data=dict(component_path=next_component))
          else:
            # There is no need to go back to the client for intermediate
            # paths in the prefix tree, just emulate this by recursively
            # calling this state inline.
            self.CallStateInline(
                [rdf_client.StatEntry(pathspec=pathspec)],
                next_state="ProcessEntry",
                request_data=dict(component_path=next_component))

      if recursions_to_get or regexes_to_get:
        # Recursions or regexes need a base pathspec to operate on. If we
        # have neither a response or a root path, we send a default pathspec
        # that opens the root with pathtype "OS".
        base_pathspec = self._GetBasePathspec(response)
        if not base_pathspec:
          base_pathspec = rdf_paths.PathSpec(path="/", pathtype="OS")

        for depth, recursions in recursions_to_get.iteritems():
          path_regex = "(?i)^" + "$|^".join(set([c.path for c in recursions
                                                ])) + "$"

          findspec = rdf_client.FindSpec(
              pathspec=base_pathspec,
              cross_devs=True,
              max_depth=depth,
              path_regex=path_regex)

          findspec.iterator.number = self.FILE_MAX_PER_DIR
          self.CallClient(
              server_stubs.Find,
              findspec,
              next_state="ProcessEntry",
              request_data=dict(base_path=component_path))

        if regexes_to_get:
          path_regex = "(?i)^" + "$|^".join(
              set([c.path for c in regexes_to_get])) + "$"
          findspec = rdf_client.FindSpec(
              pathspec=base_pathspec, max_depth=1, path_regex=path_regex)

          findspec.iterator.number = self.FILE_MAX_PER_DIR
          self.CallClient(
              server_stubs.Find,
              findspec,
              next_state="ProcessEntry",
              request_data=dict(base_path=component_path))