def StartBlobsUpload(self, binary_id: rdf_objects.SignedBinaryID, next_state: str): """Starts recursive blobs upload for a given binary_id. Args: binary_id: Binary id of the binary that should be uploaded to the client. next_state: Name of the state to be triggered when the upload is complete. """ # Fail early if the file is not there or empty. try: file_size = signed_binary_utils.FetchSizeOfSignedBinary(binary_id) except signed_binary_utils.UnknownSignedBinaryError: raise flow_base.FlowError(f"File {binary_id} not found.") if file_size == 0: raise flow_base.FlowError(f"File {binary_id} is empty.") self.CallStateInline(next_state=self.NextBlob.__name__, request_data={ "binary_id": binary_id, "blob_index": 0, "file_offset": 0, "file_size": file_size, "next_state": next_state, })
def testMissingSignedBinary(self): missing_urn = rdfvalue.RDFURN("aff4:/config/executables/not/exist") with self.assertRaises(signed_binary_utils.SignedBinaryNotFoundError): signed_binary_utils.DeleteSignedBinary(missing_urn) with self.assertRaises(signed_binary_utils.SignedBinaryNotFoundError): signed_binary_utils.FetchBlobsForSignedBinaryByURN(missing_urn) with self.assertRaises(signed_binary_utils.SignedBinaryNotFoundError): signed_binary_utils.FetchSizeOfSignedBinary(missing_urn)
def testFetchSizeOfSignedBinary(self): binary1_urn = rdfvalue.RDFURN("aff4:/config/executables/foo1") binary2_urn = rdfvalue.RDFURN("aff4:/config/executables/foo2") binary1_data = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99" binary2_blobs = [ rdf_crypto.SignedBlob().Sign(b"\x00\x11\x22", self._private_key), rdf_crypto.SignedBlob().Sign(b"\x33\x44", self._private_key) ] signed_binary_utils.WriteSignedBinary(binary1_urn, binary1_data, private_key=self._private_key, public_key=self._public_key, chunk_size=3) signed_binary_utils.WriteSignedBinaryBlobs(binary2_urn, binary2_blobs) binary1_size = signed_binary_utils.FetchSizeOfSignedBinary(binary1_urn) binary2_size = signed_binary_utils.FetchSizeOfSignedBinary(binary2_urn) self.assertEqual(binary1_size, 10) self.assertEqual(binary2_size, 5)
def Handle(self, args, token=None): root_urn = _GetSignedBlobsRoots()[args.type] binary_urn = root_urn.Add(args.path) binary_size = signed_binary_utils.FetchSizeOfSignedBinary(binary_urn) blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary(binary_urn) chunk_iterator = signed_binary_utils.StreamSignedBinaryContents( blob_iterator, chunk_size=self.CHUNK_SIZE) return api_call_handler_base.ApiBinaryStream( filename=binary_urn.Basename(), content_generator=chunk_iterator, content_length=binary_size)
def testExecuteLargeBinaries(self): client_mock = action_mocks.ActionMock(standard.ExecuteBinaryCommand) code = b"I am a large binary file" * 100 upload_path = signed_binary_utils.GetAFF4ExecutablesRoot().Add( config.CONFIG["Client.platform"]).Add("test.exe") maintenance_utils.UploadSignedConfigBlob(code, aff4_path=upload_path, limit=100, token=self.token) binary_urn = rdfvalue.RDFURN(upload_path) binary_size = signed_binary_utils.FetchSizeOfSignedBinary( binary_urn, token=self.token) blob_iterator, _ = signed_binary_utils.FetchBlobsForSignedBinary( binary_urn, token=self.token) # Total size is 2400. self.assertEqual(binary_size, 2400) # There should be 24 parts to this binary. self.assertLen(list(blob_iterator), 24) # This flow has an acl, the user needs to be admin. acl_test_lib.CreateAdminUser(self.token.username) with utils.Stubber(subprocess, "Popen", client_test_lib.Popen): flow_test_lib.TestFlowHelper(compatibility.GetName( administrative.LaunchBinary), client_mock, client_id=self.SetupClient(0), binary=upload_path, command_line="--value 356", token=self.token) # Check that the executable file contains the code string. self.assertEqual(client_test_lib.Popen.binary, code) # At this point, the actual binary should have been cleaned up by the # client action so it should not exist. self.assertRaises(IOError, open, client_test_lib.Popen.running_args[0]) # Check the binary was run with the correct command line. self.assertEqual(client_test_lib.Popen.running_args[1], "--value") self.assertEqual(client_test_lib.Popen.running_args[2], "356") # Check the command was in the tmp file. self.assertStartsWith(client_test_lib.Popen.running_args[0], config.CONFIG["Client.tempdir_roots"][0])