def FingerprintFile(self, pathspec, max_filesize=None, request_data=None): """Launch a fingerprint client action.""" request = rdf_client_action.FingerprintRequest(pathspec=pathspec) if max_filesize is not None: request.max_filesize = max_filesize # Generic hash. request.AddRequest( fp_type=rdf_client_action.FingerprintTuple.Type.FPT_GENERIC, hashers=[ rdf_client_action.FingerprintTuple.HashType.MD5, rdf_client_action.FingerprintTuple.HashType.SHA1, rdf_client_action.FingerprintTuple.HashType.SHA256 ]) # Authenticode hash. request.AddRequest( fp_type=rdf_client_action.FingerprintTuple.Type.FPT_PE_COFF, hashers=[ rdf_client_action.FingerprintTuple.HashType.MD5, rdf_client_action.FingerprintTuple.HashType.SHA1, rdf_client_action.FingerprintTuple.HashType.SHA256 ]) self.CallClient(self.fingerprint_file_mixin_client_action, request, next_state="ProcessFingerprint", request_data=request_data)
def _ScheduleHashFile(self, index: int, pathspec: rdf_paths.PathSpec) -> None: """Schedules the HashFile Client Action. Args: index: Index of the current file to be hashed. pathspec: Pathspec of the current file to be hashed. """ # Add the file tracker to the pending hashes list where it waits until the # hash comes back. self.state.pending_hashes[index] = {"index": index} request = rdf_client_action.FingerprintRequest( pathspec=pathspec, max_filesize=self.state.file_size) request.AddRequest( fp_type=rdf_client_action.FingerprintTuple.Type.FPT_GENERIC, hashers=[ rdf_client_action.FingerprintTuple.HashType.MD5, rdf_client_action.FingerprintTuple.HashType.SHA1, rdf_client_action.FingerprintTuple.HashType.SHA256 ]) self.CallClient( server_stubs.HashFile, request, next_state=compatibility.GetName(self._ReceiveFileHash), request_data=dict(index=index))
def testHashFile(self): """Can we hash a file?""" path = os.path.join(self.base_path, "numbers.txt") p = rdf_paths.PathSpec(path=path, pathtype=rdf_paths.PathSpec.PathType.OS) result = self.RunAction( file_fingerprint.FingerprintFile, rdf_client_action.FingerprintRequest(pathspec=p)) types = result[0].matching_types fingers = {} for f in result[0].results: fingers[f["name"]] = f generic_sha256 = fingers["generic"]["sha256"] self.assertEqual(generic_sha256, hashlib.sha256(open(path, "rb").read()).digest()) # Make sure all fingers are listed in types and vice versa. t_map = { rdf_client_action.FingerprintTuple.Type.FPT_GENERIC: "generic", rdf_client_action.FingerprintTuple.Type.FPT_PE_COFF: "pecoff" } ti_map = dict((v, k) for k, v in iteritems(t_map)) for t in types: self.assertIn(t_map[t], fingers) for f in fingers: self.assertIn(ti_map[f], types) self.assertEqual(result[0].pathspec.path, path)
def testMissingFile(self): """Fail on missing file?""" path = os.path.join(self.base_path, "this file does not exist") p = rdf_paths.PathSpec(path=path, pathtype=rdf_paths.PathSpec.PathType.OS) self.assertRaises(IOError, self.RunAction, file_fingerprint.FingerprintFile, rdf_client_action.FingerprintRequest(pathspec=p))
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 not self.client_version or self.client_version >= 3221: stub = server_stubs.GetFileStat request = rdf_client_action.GetFileStatRequest(pathspec=pathspec) request.follow_symlink = True request_name = "GetFileStat" else: stub = server_stubs.StatFile request = rdf_client_action.ListDirRequest(pathspec=pathspec) request_name = "StatFile" self.CallClient(stub, request, next_state=compatibility.GetName(self._StoreStat), request_data=dict(index=index, request_name=request_name)) request = rdf_client_action.FingerprintRequest( pathspec=pathspec, max_filesize=self.state.file_size) request.AddRequest( fp_type=rdf_client_action.FingerprintTuple.Type.FPT_GENERIC, hashers=[ rdf_client_action.FingerprintTuple.HashType.MD5, rdf_client_action.FingerprintTuple.HashType.SHA1, rdf_client_action.FingerprintTuple.HashType.SHA256 ]) self.CallClient(server_stubs.HashFile, request, next_state=compatibility.GetName( self._ReceiveFileHash), request_data=dict(index=index))