///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
| 673 | |
| 674 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 675 | void FSecure::C3::Core::Profiler::Agent::PerformCreateCommand(json const& jCommandElement) |
| 676 | { |
| 677 | auto profiler = m_Owner.lock(); |
| 678 | if (!profiler) |
| 679 | return; // probably shutting down |
| 680 | |
| 681 | auto gateRelay = profiler->m_Gateway->m_Gateway.lock(); |
| 682 | if (!gateRelay) |
| 683 | return; // probably shutting down |
| 684 | |
| 685 | auto route = gateRelay->FindRoute(m_Id); |
| 686 | if (!route) |
| 687 | throw std::runtime_error("Failed to find route to agent id = " + m_Id.ToString()); |
| 688 | |
| 689 | auto commandWithArguments = base64::decode<ByteVector>(jCommandElement["Command"]["ByteForm"].get<std::string>()); |
| 690 | |
| 691 | // check if command is a create device command -> then we need to assign deviceId and retreive its hash and repack commandWithArguments |
| 692 | // [CommandId{CreateAndAttachDevice}(u16)][NewDeviceId(u16)][NewDeviceTypeHash(HashT)][arguments] |
| 693 | auto commandReadView = ByteView{ commandWithArguments }; |
| 694 | auto commandId = commandReadView.Read<std::uint16_t>(); |
| 695 | auto const& createCommands = profiler->m_Gateway->m_CreateCommands; |
| 696 | auto command = std::find_if(createCommands.cbegin(), createCommands.cend(), [commandId](Gateway::CreateCommand const& cc) { return cc.m_IsDevice && cc.m_Id == commandId; }); |
| 697 | |
| 698 | // this function will only suport create commands |
| 699 | if (command == createCommands.cend()) |
| 700 | return; |
| 701 | |
| 702 | // it is a create command |
| 703 | DeviceId newDeviceId = ++m_LastDeviceId; |
| 704 | ByteVector repacked; |
| 705 | repacked.Write(Command::AddDevice, newDeviceId, command->m_IsNegotiableChannel, command->m_Hash); |
| 706 | if (auto binder = profiler->GetBinderTo(command->m_Hash); binder && command->m_IsDevice) // peripheral, check if payload is needed. |
| 707 | { |
| 708 | auto connector = profiler->m_Gateway->m_Gateway.lock()->GetConnector(binder); |
| 709 | if (!connector) |
| 710 | throw std::runtime_error{ "Connector for requested peripheral is closed" }; |
| 711 | |
| 712 | auto updatedArguments = connector->PeripheralCreationCommand(ByteVector::Create(RouteId{ route->m_RouteId.GetAgentId(), newDeviceId }), commandReadView, m_IsX64); |
| 713 | repacked.Concat(updatedArguments); |
| 714 | } |
| 715 | else |
| 716 | { |
| 717 | repacked.Concat(commandReadView); |
| 718 | } |
| 719 | |
| 720 | commandWithArguments = repacked; |
| 721 | |
| 722 | auto outgoingChannel = route->m_Channel.lock(); |
| 723 | if (!outgoingChannel) |
| 724 | throw std::runtime_error("Tried to send command through dead channel"); // TODO maybe try through different route |
| 725 | |
| 726 | // push json with startup arguments to some container, use it if channel is created. |
| 727 | AddScheduledDevice(newDeviceId, jCommandElement["Command"]); |
| 728 | |
| 729 | auto query = ProceduresG2X::RunCommandOnAgentQuery::Create(route->m_RouteId, gateRelay->m_Signature, m_EncryptionKey, gateRelay->m_DecryptionKey, commandWithArguments); |
| 730 | gateRelay->LockAndSendPacket(query->ComposeQueryPacket(), outgoingChannel); |
| 731 | } |
| 732 |
nothing calls this directly
no test coverage detected