M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +1 -0
@@ 21,6 21,7 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('gs_eula_accepted', '0'),
('gs_onboarding_done', '0'),
('gs_usb_security', '1'),
+ ('gs_usb_devices', ''),
('gs_os_update_version', '0.00.0'),
('gs_os_current_version', '0.00.0'),
('bt_state', '0'),
M module-apps/application-desktop/widgets/PinLockHandler.cpp => module-apps/application-desktop/widgets/PinLockHandler.cpp +0 -2
@@ 93,8 93,6 @@ namespace gui
if (app->getCurrentWindow()->getName() == app::window::name::desktop_pin_lock) {
app->switchWindow(app::window::name::desktop_main_window);
}
- app->bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeUnlocked>(),
- service::name::service_desktop);
return;
}
M module-bsp/board/rt1051/bsp/usb => module-bsp/board/rt1051/bsp/usb +1 -1
@@ 1,1 1,1 @@
-Subproject commit ed8055cf9a7160772ab502b938689088e83f59b1
+Subproject commit 9f9b3f988333f30631caa3b442d57d2b44f7e074
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "endpoints/developerMode/event/ATRequest.hpp"
M module-services/service-db/agents/settings/Settings.cpp => module-services/service-db/agents/settings/Settings.cpp +4 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <service-db/Settings.hpp>
@@ 132,7 132,7 @@ namespace settings
}
cbValues[path].first = std::move(cb);
- auto msg = std::make_shared<settings::Messages::RegisterOnVariableChange>(path);
+ auto msg = std::make_shared<settings::Messages::RegisterOnVariableChange>(path);
sendMsg(std::move(msg));
}
@@ 151,7 151,7 @@ namespace settings
}
cbValues[path].second = std::move(cb);
- auto msg = std::make_shared<settings::Messages::RegisterOnVariableChange>(path);
+ auto msg = std::make_shared<settings::Messages::RegisterOnVariableChange>(path);
sendMsg(std::move(msg));
}
@@ 171,7 171,7 @@ namespace settings
cbValues.erase(it_cb);
}
- auto msg = std::make_shared<settings::Messages::UnregisterOnVariableChange>(path);
+ auto msg = std::make_shared<settings::Messages::UnregisterOnVariableChange>(path);
sendMsg(std::move(msg));
}
M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +1 -0
@@ 10,6 10,7 @@ namespace settings
constexpr inline auto activeSim = "gs_active_sim";
constexpr inline auto lockPassHash = "gs_lock_pass_hash";
constexpr inline auto usbSecurity = "gs_usb_security";
+ constexpr inline auto usbDevices = "gs_usb_devices";
constexpr inline auto lockScreenPasscodeIsOn = "gs_lock_screen_passcode_is_on";
constexpr inline auto lockTime = "gs_lock_time";
constexpr inline auto displayLanguage = "gs_display_language";
M module-services/service-desktop/CMakeLists.txt => module-services/service-desktop/CMakeLists.txt +2 -0
@@ 27,6 27,7 @@ set(SOURCES
endpoints/filesystem/FilesystemEndpoint.cpp
endpoints/calendarEvents/CalendarEventsHelper.cpp
endpoints/calendarEvents/CalendarEventsEndpoint.cpp
+ endpoints/security/SecurityEndpoint.cpp
parser/HttpEnums.cpp
parser/ParserFSM.cpp
@@ 37,6 38,7 @@ set(SOURCES
DesktopMessages.cpp
ServiceDesktop.cpp
WorkerDesktop.cpp
+ USBSecurityModel.cpp
)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
M module-services/service-desktop/DesktopMessages.cpp => module-services/service-desktop/DesktopMessages.cpp +1 -0
@@ 52,4 52,5 @@ namespace sdesktop
context.setResponseBody(json11::Json::object{{json::bluetooth::scan, json::bluetooth::btOff}});
}
} // namespace bluetooth
+
} // namespace sdesktop
M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +53 -20
@@ 60,8 60,9 @@ ServiceDesktop::ServiceDesktop() : sys::Service(service::name::service_desktop,
{
LOG_INFO("[ServiceDesktop] Initializing");
- updateOS = std::make_unique<UpdateMuditaOS>(this);
- settings = std::make_unique<settings::Settings>(this);
+ updateOS = std::make_unique<UpdateMuditaOS>(this);
+ settings = std::make_unique<settings::Settings>(this);
+ usbSecurityModel = std::make_unique<sdesktop::USBSecurityModel>(this, settings.get());
}
ServiceDesktop::~ServiceDesktop()
@@ 71,7 72,7 @@ ServiceDesktop::~ServiceDesktop()
sys::ReturnCodes ServiceDesktop::InitHandler()
{
- desktopWorker = std::make_unique<WorkerDesktop>(this);
+ desktopWorker = std::make_unique<WorkerDesktop>(this, *usbSecurityModel.get());
const bool ret =
desktopWorker->init({{sdesktop::RECEIVE_QUEUE_BUFFER_NAME, sizeof(std::string *), sdesktop::cdc_queue_len},
{sdesktop::SEND_QUEUE_BUFFER_NAME, sizeof(std::string *), sdesktop::cdc_queue_object_size},
@@ 94,7 95,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
request->event->send();
}
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
});
connect(sdesktop::BackupMessage(), [&](sys::Message *msg) {
@@ 105,7 106,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
backupStatus.location =
(purefs::dir::getBackupOSPath() / backupStatus.task).replace_extension(purefs::extension::tar);
}
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
});
connect(sdesktop::RestoreMessage(), [&](sys::Message *msg) {
@@ 114,7 115,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
RemountFS();
BackupRestore::RestoreUserFiles(this);
}
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
});
connect(sdesktop::FactoryMessage(), [&](sys::Message *msg) {
@@ 127,7 128,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
// this might theoretically cause filesystem corruption
FactoryReset::Run(this);
}
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
});
connect(sdesktop::UpdateOsMessage(), [&](sys::Message *msg) {
@@ 159,7 160,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
}
}
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
});
connect(sdesktop::transfer::TransferTimerState(), [&](sys::Message *msg) {
@@ 184,34 185,52 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
break;
}
}
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
});
connect(sdesktop::usb::USBConfigured(), [&](sys::Message *msg) {
- if (!desktopWorker->isEndpointSecurityEnabled()) {
+ if (!usbSecurityModel->isSecurityEnabled()) {
LOG_INFO("Endpoint security disabled.");
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
}
LOG_INFO("USB connected with endpoint security enabled. Requesting passcode.");
- desktopWorker->setEndpointSecurity(EndpointSecurity::Block);
+ usbSecurityModel->setEndpointSecurity(EndpointSecurity::Block);
bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeRequest>(),
app::manager::ApplicationManager::ServiceName);
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
});
connect(sdesktop::usb::USBDisconnected(), [&](sys::Message *msg) {
LOG_INFO("USB disconnected. Enabling secured endpoints.");
bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeRequest>(true),
app::manager::ApplicationManager::ServiceName);
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
+ });
+
+ connect(sdesktop::usb::USBHandshake(), [&](sys::Message *msg) {
+ auto handshakeMsg = dynamic_cast<sdesktop::usb::USBHandshake *>(msg);
+ processUSBHandshake(handshakeMsg);
+ return sys::MessageNone{};
+ });
+
+ connect(sdesktop::usb::USBSecurityOn(), [&](sys::Message *msg) {
+ usbSecurityModel->enableEndpointSecurity(true);
+ return sys::MessageNone{};
+ });
+
+ connect(sdesktop::usb::USBSecurityOff(), [&](sys::Message *msg) {
+ usbSecurityModel->enableEndpointSecurity(false);
+ return sys::MessageNone{};
});
connect(sdesktop::passcode::ScreenPasscodeUnlocked(), [&](sys::Message *msg) {
- LOG_INFO("Passcode accepted. Enabling secured endpoints.");
- desktopWorker->setEndpointSecurity(EndpointSecurity::Allow);
- return std::make_shared<sys::ResponseMessage>();
+ LOG_INFO("Passcode accepted. Enabling endpoints.");
+ bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeRequest>(true),
+ app::manager::ApplicationManager::ServiceName);
+ usbSecurityModel->setEndpointSecurity(EndpointSecurity::Allow);
+ return sys::MessageNone{};
});
settings->registerValueChange(updateos::settings::history,
@@ 221,9 240,8 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
::settings::SystemProperties::usbSecurity,
[this](std::string value) {
bool securityEnabled = utils::getNumericValue<bool>(value);
- LOG_INFO("Setting endpoint security: %d", securityEnabled);
- desktopWorker->enableEndpointSecurity(securityEnabled);
- desktopWorker->setEndpointSecurity(securityEnabled ? EndpointSecurity::Block : EndpointSecurity::Allow);
+ usbSecurityModel->enableEndpointSecurity(securityEnabled);
+ usbSecurityModel->setEndpointSecurity(securityEnabled ? EndpointSecurity::Block : EndpointSecurity::Allow);
},
settings::SettingsScope::Global);
@@ 280,3 298,18 @@ void ServiceDesktop::prepareBackupData()
backupStatus.state = false;
backupStatus.backupTempDir = purefs::dir::getTemporaryPath() / backupStatus.task;
}
+
+void ServiceDesktop::processUSBHandshake(sdesktop::usb::USBHandshake *msg)
+{
+ parserFSM::Context responseContext;
+ responseContext.setEndpoint(parserFSM::EndpointType::usbSecurity);
+ responseContext.setResponseStatus(parserFSM::http::Code::Forbidden);
+
+ if (usbSecurityModel->processHandshake(msg)) {
+ LOG_DEBUG("Handshake ok. Unlocking.");
+ bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeUnlocked>(), service::name::service_desktop);
+ responseContext.setResponseStatus(parserFSM::http::Code::OK);
+ }
+
+ parserFSM::MessageHandler::putToSendQueue(responseContext.createSimpleResponse());
+}
A module-services/service-desktop/USBSecurityModel.cpp => module-services/service-desktop/USBSecurityModel.cpp +116 -0
@@ 0,0 1,116 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "service-desktop/USBSecurityModel.hpp"
+
+#include "Service/Service.hpp"
+#include "service-desktop/DesktopMessages.hpp"
+#include "service-desktop/WorkerDesktop.hpp"
+
+#include <service-db/service-db/Settings.hpp>
+#include <module-services/service-db/agents/settings/SystemSettings.hpp>
+
+namespace sdesktop
+{
+ USBSecurityModel::USBSecurityModel(sys::Service *ownerSrv, settings::Settings *srvSettings)
+ {
+ settings = srvSettings;
+
+ settings->registerValueChange(
+ settings::SystemProperties::usbDevices,
+ [this](const std::string &value) { bound = parseDevices(value); },
+ ::settings::SettingsScope::Global);
+
+ settings->registerValueChange(
+ ::settings::SystemProperties::lockPassHash,
+ [this](const std::string &value) {
+ // test
+ lockPassHash = utils::getNumericValue<unsigned int>(value);
+ },
+ ::settings::SettingsScope::Global);
+ }
+
+ auto USBSecurityModel::isBound(DeviceID id) const -> bool
+ {
+ return bound.find(id) != bound.end();
+ }
+
+ auto USBSecurityModel::addDevice(DeviceID id, Passcode passcode) -> bool
+ {
+ if (endpointSecurity == EndpointSecurity::Block && !checkPasscode(passcode)) {
+ return false;
+ }
+
+ bound.insert(id);
+ settings->setValue(settings::SystemProperties::usbDevices, dumpDevices(bound));
+
+ return true;
+ }
+
+ bool USBSecurityModel::checkPasscode(const Passcode &passcode)
+ {
+ static std::hash<unsigned int> hashEngine;
+ auto hash = hashEngine(passcode);
+ return hash == lockPassHash;
+ }
+
+ auto USBSecurityModel::isSecurityEnabled() const -> bool
+ {
+#ifdef DISABLE_USB_SECURITY
+ return false;
+#else
+ return utils::getNumericValue<bool>(
+ settings->getValue(settings::SystemProperties::usbSecurity, settings::SettingsScope::Global));
+#endif
+ }
+
+ void USBSecurityModel::enableEndpointSecurity(bool securityEnabled)
+ {
+ settings->setValue(settings::SystemProperties::usbSecurity,
+ utils::to_string(securityEnabled),
+ settings::SettingsScope::Global);
+ }
+
+ bool USBSecurityModel::processHandshake(const sdesktop::usb::USBHandshake *handshake)
+ {
+ auto id = handshake->getId();
+ auto pwd = handshake->getPasscode();
+
+ LOG_DEBUG("Process handshake: id=%s; pwd=%d;", id.c_str(), pwd);
+
+ if (isBound(id)) {
+ LOG_DEBUG("Bounded device, handshake successfull");
+ return true;
+ }
+
+ if (addDevice(id, pwd)) {
+ LOG_DEBUG("Bounding device successfull");
+ return true;
+ }
+
+ LOG_DEBUG("Handshake failed");
+ return false;
+ }
+
+ void USBSecurityModel::setEndpointSecurity(EndpointSecurity security)
+ {
+ endpointSecurity = security;
+ }
+
+ auto USBSecurityModel::getEndpointSecurity() const -> EndpointSecurity
+ {
+ return endpointSecurity;
+ }
+
+ std::set<DeviceID> USBSecurityModel::parseDevices(const std::string &value) const
+ {
+ std::istringstream iss{value};
+ return {std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>()};
+ }
+ std::string USBSecurityModel::dumpDevices(const std::set<DeviceID> &devices) const
+ {
+ std::stringstream ss;
+ std::copy(devices.begin(), devices.end(), std::ostream_iterator<DeviceID>(ss, " "));
+ return ss.str();
+ }
+} // namespace sdesktop<
\ No newline at end of file
M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +4 -4
@@ 18,9 18,9 @@
inline constexpr auto uploadFailedMessage = "file upload terminated before all data transferred";
-WorkerDesktop::WorkerDesktop(sys::Service *ownerServicePtr)
- : sys::Worker(ownerServicePtr, sdesktop::worker_stack), ownerService(ownerServicePtr), parser(ownerServicePtr),
- fileDes(nullptr)
+WorkerDesktop::WorkerDesktop(sys::Service *ownerServicePtr, const sdesktop::USBSecurityModel &securityModel)
+ : sys::Worker(ownerServicePtr, sdesktop::worker_stack), fileDes(nullptr), securityModel(securityModel),
+ ownerService(ownerServicePtr), parser(ownerServicePtr)
{}
bool WorkerDesktop::init(std::list<sys::WorkerQueueInfo> queues)
@@ 64,7 64,7 @@ bool WorkerDesktop::handleMessage(uint32_t queueID)
return false;
}
- auto factory = std::make_unique<SecuredEndpointFactory>(endpointSecurity);
+ auto factory = std::make_unique<SecuredEndpointFactory>(securityModel.getEndpointSecurity());
auto handler = std::make_unique<parserFSM::MessageHandler>(ownerService, std::move(factory));
parser.setMessageHandler(std::move(handler));
M module-services/service-desktop/endpoints/Context.hpp => module-services/service-desktop/endpoints/Context.hpp +4 -0
@@ 8,6 8,10 @@
namespace parserFSM
{
+ constexpr http::Code toCode(bool r)
+ {
+ return r ? http::Code::OK : http::Code::InternalServerError;
+ }
namespace json
{
M module-services/service-desktop/endpoints/EndpointFactory.hpp => module-services/service-desktop/endpoints/EndpointFactory.hpp +4 -1
@@ 19,6 19,7 @@
#include "restore/RestoreEndpoint.hpp"
#include "update/UpdateEndpoint.hpp"
#include <endpoints/bluetooth/BluetoothEndpoint.hpp>
+#include <module-services/service-desktop/endpoints/security/SecurityEndpoint.hpp>
class EndpointFactory
{
@@ 53,6 54,8 @@ class EndpointFactory
return std::make_unique<CalendarEventsEndpoint>(ownerServicePtr);
case parserFSM::EndpointType::bluetooth:
return std::make_unique<BluetoothEndpoint>(ownerServicePtr);
+ case parserFSM::EndpointType::usbSecurity:
+ return std::make_unique<SecurityEndpoint>(ownerServicePtr);
default:
return nullptr;
}
@@ 67,7 70,7 @@ enum class EndpointSecurity
class SecuredEndpointFactory : public EndpointFactory
{
- static constexpr auto Whitelist = {parserFSM::EndpointType::developerMode};
+ static constexpr auto Whitelist = {parserFSM::EndpointType::developerMode, parserFSM::EndpointType::usbSecurity};
public:
explicit SecuredEndpointFactory(EndpointSecurity security) : endpointSecurity(security)
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +3 -6
@@ 33,10 33,6 @@ using namespace parserFSM;
namespace
{
- constexpr http::Code toCode(bool r)
- {
- return r ? http::Code::OK : http::Code::InternalServerError;
- }
auto toTetheringState(const std::string &state) -> sys::phone_modes::Tethering
{
@@ 116,13 112,14 @@ auto DeveloperModeHelper::processPut(Context &context) -> ProcessResult
service::name::system_manager);
return {sent::delayed, std::nullopt};
}
- else if (body[json::developerMode::usbSecurity].is_string()) {
+ else if (body[json::developerMode::usbSecurityStatus].is_string()) {
std::shared_ptr<sys::DataMessage> msg = std::make_shared<sdesktop::usb::USBConfigured>();
- if (body[json::developerMode::usbSecurity].string_value() == json::developerMode::usbUnlock) {
+ if (body[json::developerMode::usbSecurityStatus].string_value() == json::developerMode::usbUnlocked) {
msg = std::make_shared<sdesktop::passcode::ScreenPasscodeUnlocked>();
}
code = toCode(owner->bus.sendUnicast(std::move(msg), "ServiceDesktop"));
}
+
else {
context.setResponseStatus(http::Code::BadRequest);
MessageHandler::putToSendQueue(context.createSimpleResponse());
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp +4 -4
@@ 57,7 57,7 @@ namespace parserFSM
inline constexpr auto changeCellularStateCmd = "changeCellularStateCmd";
inline constexpr auto getInfo = "getInfo";
inline constexpr auto tethering = "tethering";
- inline constexpr auto usbSecurity = "usbSecurity";
+ inline constexpr auto usbSecurityStatus = "usbSecurityStatus";
/// values for getInfo cmd
inline constexpr auto simStateInfo = "simState";
inline constexpr auto cellularStateInfo = "cellularState";
@@ 69,9 69,9 @@ namespace parserFSM
inline constexpr auto tetheringOn = "on";
inline constexpr auto tetheringOff = "off";
- /// values for usbSecurity
- inline constexpr auto usbLock = "usbLock";
- inline constexpr auto usbUnlock = "usbUnlock";
+ // values for usb security
+ inline constexpr auto usbLocked = "locked";
+ inline constexpr auto usbUnlocked = "unlocked";
} // namespace json::developerMode
A module-services/service-desktop/endpoints/security/SecurityEndpoint.cpp => module-services/service-desktop/endpoints/security/SecurityEndpoint.cpp +74 -0
@@ 0,0 1,74 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "SecurityEndpoint.hpp"
+
+#include <endpoints/Context.hpp>
+#include <parser/MessageHandler.hpp>
+#include <service-desktop/service-desktop/ServiceDesktop.hpp>
+#include <service-desktop/DesktopMessages.hpp>
+#include <json/json11.hpp>
+
+#include <string>
+
+using namespace parserFSM;
+
+auto SecurityEndpoint::handle(parserFSM::Context &context) -> void
+{
+ http::Code responseCode;
+ switch (context.getMethod()) {
+ case http::Method::get:
+ responseCode = processStatus(context);
+ context.setResponseStatus(responseCode);
+ parserFSM::MessageHandler::putToSendQueue(context.createSimpleResponse());
+ break;
+ case http::Method::put:
+ responseCode = processConfiguration(context);
+ context.setResponseStatus(responseCode);
+ parserFSM::MessageHandler::putToSendQueue(context.createSimpleResponse());
+ break;
+ case http::Method::post:
+ processHandshake(context);
+ break;
+ default:
+ responseCode = http::Code::BadRequest;
+ context.setResponseStatus(responseCode);
+ parserFSM::MessageHandler::putToSendQueue(context.createSimpleResponse());
+ break;
+ }
+}
+
+auto SecurityEndpoint::processHandshake(Context &context) -> http::Code
+{
+ auto body = context.getBody();
+ if (!body[json::usb::id].is_string()) {
+ return http::Code::BadRequest;
+ }
+
+ auto msg = std::make_shared<sdesktop::usb::USBHandshake>(body[json::usb::id].string_value(),
+ body[json::usb::passcode].int_value());
+ return toCode(ownerServicePtr->bus.sendUnicast(msg, service::name::service_desktop));
+}
+
+auto SecurityEndpoint::processStatus(Context &context) -> http::Code
+{
+ auto desktopService = dynamic_cast<ServiceDesktop *>(ownerServicePtr);
+ auto security = desktopService->getSecurity()->getEndpointSecurity();
+ return security == EndpointSecurity::Allow ? http::Code::OK : http::Code::Forbidden;
+}
+
+auto SecurityEndpoint::processConfiguration(Context &context) -> http::Code
+{
+ auto body = context.getBody();
+
+ std::shared_ptr<sys::DataMessage> msg;
+
+ if (body[json::usb::status].string_value() == json::usb::on) {
+ msg = std::make_shared<sdesktop::usb::USBSecurityOn>();
+ }
+ if (body[json::usb::status].string_value() == json::usb::off) {
+ msg = std::make_shared<sdesktop::usb::USBSecurityOff>();
+ }
+
+ return toCode(ownerServicePtr->bus.sendUnicast(std::move(msg), service::name::service_desktop));
+}
A module-services/service-desktop/endpoints/security/SecurityEndpoint.hpp => module-services/service-desktop/endpoints/security/SecurityEndpoint.hpp +35 -0
@@ 0,0 1,35 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Service/Service.hpp>
+#include <endpoints/Endpoint.hpp>
+#include <parser/ParserUtils.hpp>
+
+#include <string>
+
+namespace parserFSM
+{
+ class Context;
+} // namespace parserFSM
+
+namespace sys
+{
+ class Service;
+} // namespace sys
+
+class SecurityEndpoint : public parserFSM::Endpoint
+{
+ public:
+ explicit SecurityEndpoint(sys::Service *ownerServicePtr) : Endpoint(ownerServicePtr)
+ {
+ debugName = "SecurityEndpoint";
+ }
+ auto handle(parserFSM::Context &context) -> void override;
+
+ private:
+ auto processHandshake(parserFSM::Context &context) -> parserFSM::http::Code;
+ auto processConfiguration(parserFSM::Context &context) -> parserFSM::http::Code;
+ auto processStatus(parserFSM::Context &context) -> parserFSM::http::Code;
+};
M module-services/service-desktop/parser/ParserUtils.hpp => module-services/service-desktop/parser/ParserUtils.hpp +17 -2
@@ 27,10 27,11 @@ namespace parserFSM
calllog,
calendarEvents,
developerMode,
- bluetooth
+ bluetooth,
+ usbSecurity
};
- inline constexpr auto lastEndpoint = static_cast<int>(EndpointType::bluetooth);
+ inline constexpr auto lastEndpoint = static_cast<int>(EndpointType::usbSecurity);
// Message defs and utils
namespace message
{
@@ 169,6 170,20 @@ namespace parserFSM
inline constexpr auto templateID = "templateID";
} // namespace messages
+ namespace usb
+ {
+ inline constexpr auto passcode = "passcode";
+ inline constexpr auto id = "uniqueId";
+ inline constexpr auto config = "config";
+ inline constexpr auto status = "usbSecurityStatus";
+ inline constexpr auto on = "on";
+ inline constexpr auto off = "off";
+ inline constexpr auto locked = "locked";
+ inline constexpr auto unlocked = "unlocked";
+ inline constexpr auto security = "usbSecurity";
+
+ } // namespace usb
+
} // namespace json
} // namespace parserFSM
M module-services/service-desktop/service-desktop/DesktopMessages.hpp => module-services/service-desktop/service-desktop/DesktopMessages.hpp +41 -0
@@ 97,6 97,46 @@ namespace sdesktop
~USBDisconnected() override = default;
};
+ class USBSecurityOn : public sys::DataMessage
+ {
+ public:
+ USBSecurityOn() : sys::DataMessage(MessageType::USBSecurityOn)
+ {}
+ ~USBSecurityOn() override = default;
+ };
+
+ class USBSecurityOff : public sys::DataMessage
+ {
+ public:
+ USBSecurityOff() : sys::DataMessage(MessageType::USBSecurityOff)
+ {}
+ ~USBSecurityOff() override = default;
+ };
+
+ class USBHandshake : public sys::DataMessage
+ {
+ public:
+ USBHandshake() : sys::DataMessage(MessageType::USBHandshake)
+ {}
+ USBHandshake(const std::string &id, unsigned int passcode)
+ : sys::DataMessage(MessageType::USBHandshake), id(id), passcode(passcode)
+ {}
+ ~USBHandshake() override = default;
+
+ auto getId() const -> std::string
+ {
+ return id;
+ }
+ auto getPasscode() const
+ {
+ return passcode;
+ }
+
+ private:
+ const std::string id;
+ const unsigned int passcode = 0;
+ }; // namespace usb
+
} // namespace usb
namespace passcode
@@ 196,4 236,5 @@ namespace sdesktop
~TransferTimerState() override = default;
};
} // namespace transfer
+
} // namespace sdesktop
M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +10 -0
@@ 12,6 12,7 @@
#include "Service/Service.hpp" // for Service
#include "Constants.hpp"
#include "WorkerDesktop.hpp"
+#include "USBSecurityModel.hpp"
#include <endpoints/update/UpdateMuditaOS.hpp>
#include <service-db/DBServiceName.hpp>
@@ 63,14 64,23 @@ class ServiceDesktop : public sys::Service
std::unique_ptr<UpdateMuditaOS> updateOS;
std::unique_ptr<WorkerDesktop> desktopWorker;
+
void storeHistory(const std::string &historyValue);
void prepareBackupData();
const BackupStatus getBackupStatus()
{
return backupStatus;
}
+ const sdesktop::USBSecurityModel *getSecurity()
+ {
+ return usbSecurityModel.get();
+ }
+
+ private:
+ void processUSBHandshake(sdesktop::usb::USBHandshake *msg);
private:
+ std::unique_ptr<sdesktop::USBSecurityModel> usbSecurityModel;
std::unique_ptr<settings::Settings> settings;
std::unique_ptr<sys::Timer> transferTimer;
};
A module-services/service-desktop/service-desktop/USBSecurityModel.hpp => module-services/service-desktop/service-desktop/USBSecurityModel.hpp +56 -0
@@ 0,0 1,56 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <service-desktop/endpoints/EndpointFactory.hpp>
+
+namespace settings
+{
+ class Settings;
+}
+
+namespace sys
+{
+ class Service;
+}
+
+namespace sdesktop
+{
+ namespace usb
+ {
+ class USBHandshake;
+ };
+
+ using DeviceID = std::string;
+ using Passcode = unsigned int;
+
+ class USBSecurityModel
+ {
+ public:
+ explicit USBSecurityModel(sys::Service *ownerSrv, settings::Settings *srvSettings);
+
+ auto isBound(DeviceID id) const -> bool;
+ auto addDevice(DeviceID id, Passcode passcode) -> bool;
+ bool checkPasscode(const Passcode &passcode);
+
+ auto isSecurityEnabled() const -> bool;
+ void enableEndpointSecurity(bool securityEnabled);
+
+ bool processHandshake(const sdesktop::usb::USBHandshake *handshake);
+
+ void setEndpointSecurity(EndpointSecurity security);
+
+ auto getEndpointSecurity() const -> EndpointSecurity;
+
+ private:
+ std::set<DeviceID> parseDevices(const std::string &value) const;
+ std::string dumpDevices(const std::set<DeviceID> &devices) const;
+
+ private:
+ unsigned int lockPassHash = 0;
+ EndpointSecurity endpointSecurity;
+ std::set<DeviceID> bound;
+ settings::Settings *settings;
+ };
+}; // namespace sdesktop
M module-services/service-desktop/service-desktop/WorkerDesktop.hpp => module-services/service-desktop/service-desktop/WorkerDesktop.hpp +5 -21
@@ 12,6 12,7 @@
#include "parser/ParserFSM.hpp"
#include "endpoints/EndpointFactory.hpp"
#include "bsp/usb/usb.hpp"
+#include "USBSecurityModel.hpp"
class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
{
@@ 26,15 27,12 @@ class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
CancelTransfer,
};
- WorkerDesktop(sys::Service *ownerServicePtr);
+ WorkerDesktop(sys::Service *ownerServicePtr, const sdesktop::USBSecurityModel &securityModel);
virtual bool init(std::list<sys::WorkerQueueInfo> queues) override;
virtual bool deinit() override;
bool handleMessage(uint32_t queueID) override final;
- sys::Service *ownerService = nullptr;
- parserFSM::StateMachine parser;
-
xQueueHandle getReceiveQueue()
{
return receiveQueue;
@@ 48,21 46,6 @@ class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
void rawDataReceived(void *dataPtr, uint32_t dataLen) override;
bool getRawMode() const noexcept override;
- void setEndpointSecurity(EndpointSecurity security)
- {
- endpointSecurity = security;
- }
-
- void enableEndpointSecurity(bool enable)
- {
- endpointSecurityEnabled = enable;
- }
-
- bool isEndpointSecurityEnabled()
- {
- return endpointSecurityEnabled;
- }
-
private:
void uploadFileFailedResponse();
@@ 81,6 64,7 @@ class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
uint32_t writeFileDataWritten = 0;
std::filesystem::path filePath;
std::atomic<bool> rawModeEnabled = false;
- bool endpointSecurityEnabled = true;
- EndpointSecurity endpointSecurity;
+ const sdesktop::USBSecurityModel &securityModel;
+ sys::Service *ownerService = nullptr;
+ parserFSM::StateMachine parser;
};
M source/MessageType.hpp => source/MessageType.hpp +3 -0
@@ 221,6 221,9 @@ enum class MessageType
USBConnected,
USBConfigured,
USBDisconnected,
+ USBSecurityOn,
+ USBSecurityOff,
+ USBHandshake,
ScreenPasscodeRequest,
ScreenPasscodeUnlocked,
M test/harness => test/harness +1 -1
@@ 1,1 1,1 @@
-Subproject commit beb1c1351638839148f576cc63bc450e69d310a4
+Subproject commit 630bd58022e56e5b58db3f762cccd3bdc040c608
M test/pytest/service-desktop/test_connection_security.py => test/pytest/service-desktop/test_connection_security.py +63 -12
@@ 6,36 6,87 @@ from harness.interface.defs import status
from harness import utils, log
@pytest.mark.service_desktop_test
-@pytest.mark.usefixtures("usb_locked")
-@pytest.mark.skip("not working ;/")
def test_secured_endpoint(harness):
body = {}
+ harness.lock_usb()
+
ret = harness.endpoint_request("deviceInfo", "get", body)
assert ret["status"] == status["Forbidden"]
- ret = harness.endpoint_request("messages", "get", body)
+ harness.unlock_usb()
+
+ ret = harness.endpoint_request("deviceInfo", "get", body)
+ assert ret["status"] == status["OK"]
+
+@pytest.mark.service_desktop_test
+def test_secured_paired(harness):
+ body = {
+ "uniqueId": "11111",
+ "passcode": 3333
+ }
+
+ harness.lock_usb()
+
+ ret = harness.endpoint_request("deviceInfo", "get", {})
assert ret["status"] == status["Forbidden"]
- ret = harness.endpoint_request("calllog", "get", body)
+ ret = harness.endpoint_request("usbSecurity", "post", {
+ "uniqueId": "11111",
+ "passcode": 5555
+ })
assert ret["status"] == status["Forbidden"]
- ret = harness.endpoint_request("backup", "get", body)
+ ret = harness.endpoint_request("usbSecurity", "post", body)
+ assert ret["status"] == status["OK"]
+
+ ret = harness.endpoint_request("calllog", "get", {})
+ assert ret["status"] == status["OK"]
+
+ harness.lock_usb()
+
+ ret = harness.endpoint_request("backup", "get", {})
assert ret["status"] == status["Forbidden"]
- ret = harness.endpoint_request("contacts", "get", body)
+ ret = harness.endpoint_request("usbSecurity", "post", body)
+ assert ret["status"] == status["OK"]
+
+ ret = harness.endpoint_request("calllog", "get", {})
+ assert ret["status"] == status["OK"]
+
+ harness.lock_usb()
+
+ ret = harness.endpoint_request("usbSecurity", "post", {"uniqueId": "11111"})
+ assert ret["status"] == status["OK"]
+
+ ret = harness.endpoint_request("calllog", "get", {})
+ assert ret["status"] == status["OK"]
+
+
+@pytest.mark.service_desktop_test
+def test_usb_status(harness):
+ body = {
+ "uniqueId": "11111",
+ "passcode": 3333
+ }
+
+ harness.lock_usb()
+
+ ret = harness.endpoint_request("usbSecurity", "get", {})
assert ret["status"] == status["Forbidden"]
harness.unlock_usb()
- ret = harness.endpoint_request("deviceInfo", "get", body)
+ ret = harness.endpoint_request("usbSecurity", "get", {})
assert ret["status"] == status["OK"]
- ret = harness.endpoint_request("calllog", "get", body)
- assert ret["status"] == status["OK"]
+ harness.lock_usb()
+
+ ret = harness.endpoint_request("usbSecurity", "get", {})
+ assert ret["status"] == status["Forbidden"]
- ret = harness.endpoint_request("backup", "get", body)
- assert ret["status"] == status["BadRequest"]
+ ret = harness.endpoint_request("usbSecurity", "post", body)
+ assert ret["status"] == status["OK"]
- ret = harness.endpoint_request("contacts", "get", body)
+ ret = harness.endpoint_request("usbSecurity", "get", {})
assert ret["status"] == status["OK"]