M enabled_unittests => enabled_unittests +1 -0
@@ 225,6 225,7 @@ TESTS_LIST["catch2-service-desktop"]="
DB Helpers test - json encoding (messages);
Context class test;
Endpoint Factory test;
+ Secured Endpoint Factory test;
"
#---------
TESTS_LIST["catch2-service-desktop-endpoint-contacts"]="
M image/assets/lang/English.json => image/assets/lang/English.json +1 -0
@@ 404,6 404,7 @@
"app_settings_security_wrong_passcode": "Wrong passcode!",
"app_settings_security_passcode_changed_successfully": "Passcode changed successfully!",
"app_settings_security_passcode_disabled": "Passcode disabled!",
+ "app_settings_security_usb_passcode": "USB security",
"app_settings_apn_settings_no_apns": "<text align='center' color='9'>No APNs yet.<p>Press <b>left arrow</b> to add new.</p></text>",
"app_settings_apn_options": "Options",
"app_settings_apn_options_delete": "Delete",
M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +1 -1
@@ 20,9 20,9 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('gs_input_language', 'English'),
('gs_eula_accepted', '0'),
('gs_onboarding_done', '0'),
+ ('gs_usb_security', '1');
('bt_state', '0'),
('bt_device_visibility', '0'),
('bt_device_name', 'PurePhone'),
('bt_bonded_devices', ''),
('battery_critical_level', '0');
-
D image/user/settings.db => image/user/settings.db +0 -0
M module-apps/Application.cpp => module-apps/Application.cpp +1 -0
@@ 733,4 733,5 @@ namespace app
{
return lockScreenPasscodeIsOn;
}
+
} /* namespace app */
M module-apps/Application.hpp => module-apps/Application.hpp +19 -18
@@ 4,26 4,27 @@
#pragma once
#include "AsyncTask.hpp"
-#include "Audio/AudioCommon.hpp" // for Volume, Play...
-#include "Audio/Profiles/Profile.hpp" // for Profile, Pro...
+#include "Audio/AudioCommon.hpp" // for Volume, Play...
+#include "Audio/Profiles/Profile.hpp" // for Profile, Pro...
#include "CallbackStorage.hpp"
-#include "Service/Common.hpp" // for ReturnCodes
-#include "Service/Message.hpp" // for MessagePointer
-#include "Service/Service.hpp" // for Service
-#include "SwitchData.hpp" // for SwitchData
-#include "SystemManager/SystemManager.hpp" // for SystemManager
-#include "bsp/keyboard/key_codes.hpp" // for bsp
-#include "gui/Common.hpp" // for ShowMode
-#include "projdefs.h" // for pdMS_TO_TICKS
+
+#include "Service/Common.hpp" // for ReturnCodes
+#include "Service/Message.hpp" // for MessagePointer
+#include "Service/Service.hpp" // for Service
+#include "SwitchData.hpp" // for SwitchData
+#include "SystemManager/SystemManager.hpp" // for SystemManager
+#include "bsp/keyboard/key_codes.hpp" // for bsp
+#include "gui/Common.hpp" // for ShowMode
+#include "projdefs.h" // for pdMS_TO_TICKS
#include <service-appmgr/ApplicationManifest.hpp>
-#include <list> // for list
-#include <map> // for allocator, map
-#include <memory> // for make_shared
-#include <module-bsp/bsp/torch/torch.hpp> // for State, State...
-#include <stdint.h> // for uint32_t
-#include <string> // for string
-#include <utility> // for move, pair
-#include <vector> // for vector
+#include <list> // for list
+#include <map> // for allocator, map
+#include <memory> // for make_shared
+#include <module-bsp/bsp/torch/torch.hpp> // for State, State...
+#include <stdint.h> // for uint32_t
+#include <string> // for string
+#include <utility> // for move, pair
+#include <vector> // for vector
#include "TopBarManager.hpp"
#include "WindowsFactory.hpp"
#include "WindowsStack.hpp"
M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +6 -1
@@ 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 "ApplicationDesktop.hpp"
@@ 51,6 51,11 @@ namespace app
return actionHandled();
});
+ addActionReceiver(app::manager::actions::RequestScreenPasscode, [this](auto &&data) {
+ lockHandler.handleScreenPasscodeRequest(std::move(data));
+ return msgHandled();
+ });
+
addActionReceiver(app::manager::actions::RequestPuk, [this](auto &&data) {
lockHandler.handlePasscodeRequest(gui::PinLock::LockType::SimPuk, std::move(data));
return actionHandled();
M module-apps/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/ApplicationDesktop.hpp +2 -1
@@ 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
#pragma once
@@ 101,6 101,7 @@ namespace app
manager::actions::RequestPin,
manager::actions::RequestPuk,
manager::actions::RequestPinChange,
+ manager::actions::RequestScreenPasscode,
manager::actions::UnlockSim,
manager::actions::BlockSim,
manager::actions::ShowMMIResponse,
M module-apps/application-desktop/widgets/PinLockHandler.cpp => module-apps/application-desktop/widgets/PinLockHandler.cpp +25 -1
@@ 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 "PinLockHandler.hpp"
@@ 81,6 81,30 @@ namespace gui
}
}
+ void PinLockHandler::handleScreenPasscodeRequest(app::manager::actions::ActionParamsPtr &&data) const
+ {
+ LOG_DEBUG("Handling ScreenPasscode action");
+
+ auto params = static_cast<app::manager::actions::ScreenPasscodeParams *>(data.get());
+ auto lock = std::make_unique<gui::PinLock>(
+ Store::GSM::SIM::NONE, PinLock::LockState::PasscodeRequired, PinLock::LockType::Screen);
+
+ if (params->isCancel()) {
+ app->switchWindow(app::window::name::desktop_main_window);
+ return;
+ }
+
+ lock->onActivatedCallback = [this](PinLock::LockType type, const std::vector<unsigned int> &data) {
+ app->bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeUnlocked>(),
+ service::name::service_desktop);
+ app->switchWindow(app::window::name::desktop_main_window);
+ };
+
+ app->switchWindow(app::window::name::desktop_pin_lock,
+ gui::ShowMode::GUI_SHOW_INIT,
+ std::make_unique<gui::LockPhoneData>(std::move(lock)));
+ }
+
void PinLockHandler::handlePinChangeRequest(app::manager::actions::ActionParamsPtr &&data)
{
LOG_DEBUG("Handling RequestPinChange action");
M module-apps/application-desktop/widgets/PinLockHandler.hpp => module-apps/application-desktop/widgets/PinLockHandler.hpp +2 -1
@@ 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
#pragma once
@@ 52,6 52,7 @@ namespace gui
void handleSimBlocked(app::manager::actions::ActionParamsPtr &&data);
void handleUnlockSim(app::manager::actions::ActionParamsPtr &&data);
void handleCMEError(app::manager::actions::ActionParamsPtr &&data) const;
+ void handleScreenPasscodeRequest(app::manager::actions::ActionParamsPtr &&data) const;
[[nodiscard]] auto isScreenLocked() const noexcept -> bool
{
M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +24 -1
@@ 60,6 60,8 @@
#include <module-services/service-evtmgr/service-evtmgr/EVMessages.hpp>
#include <module-services/service-appmgr/service-appmgr/messages/Message.hpp>
#include <module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp>
+#include <module-apps/application-desktop/windows/PinLockWindow.hpp>
+#include <module-apps/application-desktop/windows/Names.hpp>
namespace app
{
@@ 222,6 224,13 @@ namespace app
},
::settings::SettingsScope::Global);
+ /*
+ settings->registerValueChange(
+ ::settings::SystemProperties::usbSecurity,
+ [this](std::string value) { usbSecured = utils::getNumericValue<bool>(value); },
+ ::settings::SettingsScope::Global);
+ */
+
return ret;
}
@@ 296,7 305,10 @@ namespace app
return std::make_unique<gui::DialogYesNo>(app, name);
});
windowsFactory.attach(gui::window::name::security, [](Application *app, const std::string &name) {
- return std::make_unique<gui::SecurityMainWindow>(app);
+ return std::make_unique<gui::SecurityMainWindow>(app, static_cast<ApplicationSettingsNew *>(app));
+ });
+ windowsFactory.attach(app::window::name::desktop_pin_lock, [&](Application *app, const std::string newname) {
+ return std::make_unique<gui::PinLockWindow>(app, app::window::name::desktop_pin_lock);
});
windowsFactory.attach(gui::window::name::change_passcode, [](Application *app, const std::string &name) {
return std::make_unique<gui::ChangePasscodeWindow>(app);
@@ 459,4 471,15 @@ namespace app
service::name::evt_manager);
}
+ bool ApplicationSettingsNew::isUSBSecured() const
+ {
+ return usbSecured;
+ }
+
+ void ApplicationSettingsNew::setUSBSecurity(bool security)
+ {
+ usbSecured = security;
+ settings->setValue(
+ ::settings::SystemProperties::usbSecurity, std::to_string(security), ::settings::SettingsScope::Global);
+ }
} /* namespace app */
M module-apps/application-settings-new/ApplicationSettings.hpp => module-apps/application-settings-new/ApplicationSettings.hpp +19 -1
@@ 112,13 112,23 @@ namespace app
virtual void setKeypadBacklightState(bool newState) = 0;
};
+ class SecuritySettings
+ {
+ public:
+ virtual ~SecuritySettings() = default;
+
+ virtual auto isUSBSecured() const -> bool = 0;
+ virtual void setUSBSecurity(bool security) = 0;
+ };
+
}; // namespace settingsInterface
class ApplicationSettingsNew : public app::Application,
public settingsInterface::SimParams,
public settingsInterface::OperatorsSettings,
public settingsInterface::ScreenLightSettings,
- public settingsInterface::KeypdBacklightSettings
+ public settingsInterface::KeypdBacklightSettings,
+ public settingsInterface::SecuritySettings
{
public:
ApplicationSettingsNew(std::string name = name_settings_new,
@@ 159,6 169,12 @@ namespace app
auto isKeypadBacklightOn() -> bool override;
void setKeypadBacklightState(bool newState) override;
+ auto isUSBSecured() const -> bool override;
+ void setUSBSecurity(bool security) override;
+
+ void setLockScreenPasscodeOn(bool passcodeOn);
+ auto isLockScreenPasscodeOn() const -> bool;
+
private:
void attachQuotesWindows();
@@ 167,6 183,8 @@ namespace app
bsp::Board board = bsp::Board::none;
bool operatorsOn = false;
bool voLteStateOn = false;
+ bool usbSecured = true;
+ bool lockScreenPasscodeOn = true;
unsigned int lockPassHash = 0;
};
M module-apps/application-settings-new/windows/SecurityMainWindow.cpp => module-apps/application-settings-new/windows/SecurityMainWindow.cpp +33 -3
@@ 1,16 1,18 @@
-// 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 "application-settings-new/ApplicationSettings.hpp"
#include "application-settings-new/data/ChangePasscodeData.hpp"
#include "module-apps/application-desktop/windows/Names.hpp"
+#include "module-apps/application-desktop/data/LockPhoneData.hpp"
#include "OptionSetting.hpp"
#include "SecurityMainWindow.hpp"
namespace gui
{
- SecurityMainWindow::SecurityMainWindow(app::Application *app)
- : BaseSettingsWindow(app, window::name::security), lockScreenPasscodeIsOn(app->isLockScreenPasscodeOn())
+ SecurityMainWindow::SecurityMainWindow(app::Application *app, app::settingsInterface::SecuritySettings *settings)
+ : BaseSettingsWindow(app, window::name::security), lockScreenPasscodeIsOn(app->isLockScreenPasscodeOn()),
+ securitySettings(settings)
{}
auto SecurityMainWindow::buildOptionsList() -> std::list<Option>
@@ 42,6 44,34 @@ namespace gui
nullptr,
lockScreenPasscodeIsOn ? option::SettingRightItem::On : option::SettingRightItem::Off));
+ optionList.emplace_back(std::make_unique<option::OptionSettings>(
+ utils::translateI18("app_settings_security_usb_passcode"),
+ [=](Item &item) {
+ auto lock = std::make_unique<gui::PinLock>(
+ Store::GSM::SIM::NONE, PinLock::LockState::PasscodeRequired, PinLock::LockType::Screen);
+ lock->onActivatedCallback = [this](PinLock::LockType type, const std::vector<unsigned int> &data) {
+ securitySettings->setUSBSecurity(!securitySettings->isUSBSecured());
+ application->returnToPreviousWindow();
+ };
+ application->switchWindow(app::window::name::desktop_pin_lock,
+ gui::ShowMode::GUI_SHOW_INIT,
+ std::make_unique<gui::LockPhoneData>(std::move(lock)));
+ return true;
+ },
+ [=](Item &item) {
+ if (item.focus) {
+ this->setBottomBarText(utils::localize.get(style::strings::common::Switch),
+ BottomBar::Side::CENTER);
+ }
+ else {
+ this->setBottomBarText(utils::localize.get(style::strings::common::select),
+ BottomBar::Side::CENTER);
+ }
+ return true;
+ },
+ nullptr,
+ securitySettings->isUSBSecured() ? option::SettingRightItem::On : option::SettingRightItem::Off));
+
if (lockScreenPasscodeIsOn) {
optionList.emplace_back(std::make_unique<option::OptionSettings>(
utils::translateI18("app_settings_security_change_passcode"),
M module-apps/application-settings-new/windows/SecurityMainWindow.hpp => module-apps/application-settings-new/windows/SecurityMainWindow.hpp +3 -2
@@ 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
#pragma once
@@ 10,11 10,12 @@ namespace gui
class SecurityMainWindow : public BaseSettingsWindow
{
public:
- explicit SecurityMainWindow(app::Application *app);
+ explicit SecurityMainWindow(app::Application *app, app::settingsInterface::SecuritySettings *settings);
private:
auto buildOptionsList() -> std::list<Option> override;
bool lockScreenPasscodeIsOn;
+ app::settingsInterface::SecuritySettings *securitySettings;
};
} // namespace gui
M module-bsp/board/linux/usb_cdc/usb_cdc.cpp => module-bsp/board/linux/usb_cdc/usb_cdc.cpp +32 -2
@@ 6,6 6,9 @@
#include <fcntl.h>
#include <fstream>
#include <string>
+#include <sys/inotify.h>
+#include <array>
+#include <limits.h>
#ifndef DEUBG_USB
#undef LOG_PRINTF
@@ 29,8 32,11 @@
namespace bsp
{
int fd;
+ int fdNofity;
xQueueHandle USBReceiveQueue;
+ xQueueHandle USBIrqQueue;
constexpr auto ptsFileName = "/tmp/purephone_pts_name";
+ char *pts_name = NULL;
#if USBCDC_ECHO_ENABLED
bool usbCdcEchoEnabled = false;
@@ 47,12 53,32 @@ namespace bsp
usbCDCReceive(ptr);
}
+ void checkUsbStatus()
+ {
+ char eventsBuff[((sizeof(inotify_event) + NAME_MAX + 1))];
+ int len = read(fdNofity, eventsBuff, ((sizeof(inotify_event) + NAME_MAX + 1)));
+ if (len > 0) {
+ const inotify_event *event = (inotify_event *)&eventsBuff[0];
+ if (event->mask & IN_OPEN) {
+ USBDeviceStatus notification = USBDeviceStatus::Connected;
+ xQueueSend(USBIrqQueue, ¬ification, 0);
+ }
+ if (event->mask & IN_CLOSE_WRITE) {
+ USBDeviceStatus notification = USBDeviceStatus::Disconnected;
+ xQueueSend(USBIrqQueue, ¬ification, 0);
+ }
+ }
+ }
+
int usbCDCReceive(void *)
{
LOG_INFO("[ServiceDesktop:BSP_Driver] Start reading on fd:%d", fd);
char inputData[SERIAL_BUFFER_LEN];
while (1) {
+
+ checkUsbStatus();
+
if (uxQueueSpacesAvailable(USBReceiveQueue) != 0) {
memset(inputData, 0, SERIAL_BUFFER_LEN);
@@ 124,7 150,7 @@ namespace bsp
std::remove(ptsFileName);
}
- int usbInit(xQueueHandle receiveQueue, USBDeviceListener *)
+ int usbInit(xQueueHandle receiveQueue, xQueueHandle irqQueue, USBDeviceListener *)
{
fd = 0;
@@ 137,12 163,15 @@ namespace bsp
grantpt(fd);
unlockpt(fd);
- char *pts_name = ptsname(fd);
+ pts_name = ptsname(fd);
if (pts_name == nullptr) {
LOG_ERROR("bsp::usbInit ptsname returned NULL, no pseudo terminal allocated");
return -1;
}
+ fdNofity = inotify_init1(O_NONBLOCK);
+ inotify_add_watch(fdNofity, pts_name, IN_OPEN | IN_CLOSE_WRITE);
+
writePtsToFile(pts_name);
LOG_INFO("bsp::usbInit linux ptsname: %s", pts_name);
struct termios newtio;
@@ 165,6 194,7 @@ namespace bsp
xTaskHandle taskHandleReceive;
USBReceiveQueue = receiveQueue;
+ USBIrqQueue = irqQueue;
BaseType_t task_error = xTaskCreate(&bsp::usbDeviceTask,
"USBLinuxReceive",
M module-bsp/board/rt1051/bsp/usb => module-bsp/board/rt1051/bsp/usb +1 -1
@@ 1,1 1,1 @@
-Subproject commit 79c274b8ab4c8d146c6c9f677fe98eda25e181a5
+Subproject commit ed8055cf9a7160772ab502b938689088e83f59b1
M module-bsp/bsp/usb/usb.hpp => module-bsp/bsp/usb/usb.hpp +15 -4
@@ 1,3 1,6 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
#pragma once
extern "C"
@@ 15,19 18,27 @@ extern "C"
#include <unistd.h>
inline constexpr auto SERIAL_BUFFER_LEN = 512;
-inline constexpr auto SERIAL_BAUDRATE = 115200;
+inline constexpr auto SERIAL_BAUDRATE = 115200;
namespace bsp
{
- class USBDeviceListener {
+ enum class USBDeviceStatus : uint32_t
+ {
+ Disconnected,
+ Connected
+ };
+
+ class USBDeviceListener
+ {
public:
- virtual bool getRawMode() const noexcept{
+ virtual bool getRawMode() const noexcept
+ {
return false;
}
virtual void rawDataReceived(void *dataPtr, uint32_t dataLen) = 0;
};
- int usbInit(xQueueHandle, USBDeviceListener *deviceListener = nullptr);
+ int usbInit(xQueueHandle, xQueueHandle, USBDeviceListener *deviceListener = nullptr);
int usbCDCReceive(void *ptr);
int usbCDCSend(std::string *sendMsg);
int usbCDCSendRaw(const char *dataPtr, size_t dataLen);
M module-services/service-appmgr/CMakeLists.txt => module-services/service-appmgr/CMakeLists.txt +1 -0
@@ 4,6 4,7 @@ message( "${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}" )
set(SOURCES
ApplicationManifest.cpp
Controller.cpp
+ data/UsbActionsParams.cpp
data/SimActionsParams.cpp
data/MmiActionsParams.cpp
model/ApplicationManager.cpp
A module-services/service-appmgr/data/UsbActionsParams.cpp => module-services/service-appmgr/data/UsbActionsParams.cpp +23 -0
@@ 0,0 1,23 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <service-appmgr/data/UsbActionsParams.hpp>
+
+using namespace app::manager::actions;
+
+ScreenPasscodeParams::ScreenPasscodeParams(bool cancel, unsigned int _attempts, std::string _passcodeName)
+ : cancel(cancel), attempts{_attempts}, passcodeName{std::move(_passcodeName)}
+{}
+
+unsigned int ScreenPasscodeParams::getAttempts() const noexcept
+{
+ return attempts;
+}
+const std::string &ScreenPasscodeParams::getPasscodeName() const noexcept
+{
+ return passcodeName;
+}
+bool ScreenPasscodeParams::isCancel() const noexcept
+{
+ return cancel;
+}
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +2 -0
@@ 20,6 20,7 @@
#include <service-gui/ServiceGUI.hpp>
#include <service-eink/ServiceEink.hpp>
#include <service-gui/Common.hpp>
+#include <service-desktop/DesktopMessages.hpp>
#include <algorithm>
#include <limits>
@@ 317,6 318,7 @@ namespace app::manager
connect(typeid(sys::CriticalBatteryLevelNotification), convertibleToActionHandler);
connect(typeid(sys::SystemBrownoutMesssage), convertibleToActionHandler);
connect(typeid(CellularSmsNoSimRequestMessage), convertibleToActionHandler);
+ connect(typeid(sdesktop::passcode::ScreenPasscodeRequest), convertibleToActionHandler);
}
sys::ReturnCodes ApplicationManager::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
M module-services/service-appmgr/service-appmgr/Actions.hpp => module-services/service-appmgr/service-appmgr/Actions.hpp +1 -0
@@ 54,6 54,7 @@ namespace app::manager
DisplayCMEError,
DisplayLowBatteryNotification,
SystemBrownout,
+ RequestScreenPasscode,
UserAction // The last enumerator in the Action enum.
// All user-defined actions shall have values greater than UserAction.
// All system-wide actions shall have values lesser than UserAction.
A module-services/service-appmgr/service-appmgr/data/UsbActionsParams.hpp => module-services/service-appmgr/service-appmgr/data/UsbActionsParams.hpp +27 -0
@@ 0,0 1,27 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <service-appmgr/service-appmgr/Actions.hpp>
+#include <module-utils/common_data/EventStore.hpp>
+
+namespace app::manager::actions
+{
+ /** Action parameters for
+ * RequestScreenPasscode
+ */
+ class ScreenPasscodeParams : public ActionParams
+ {
+ bool cancel = false;
+ unsigned int attempts = 0;
+ std::string passcodeName;
+
+ public:
+ ScreenPasscodeParams(bool cancel, unsigned int _attempts = 0, std::string _passcodeName = "Screen");
+
+ [[nodiscard]] unsigned int getAttempts() const noexcept;
+ [[nodiscard]] const std::string &getPasscodeName() const noexcept;
+ [[nodiscard]] bool isCancel() const noexcept;
+ };
+} // namespace app::manager::actions
M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +1 -0
@@ 9,6 9,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 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/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +43 -4
@@ 23,6 23,8 @@
#include <cinttypes>
#include <filesystem>
+#include <module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp>
+#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <purefs/filesystem_paths.hpp>
#include <sys/mount.h>
@@ 69,10 71,11 @@ ServiceDesktop::~ServiceDesktop()
sys::ReturnCodes ServiceDesktop::InitHandler()
{
- desktopWorker = std::make_unique<WorkerDesktop>(this);
- 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}});
+ desktopWorker = std::make_unique<WorkerDesktop>(this);
+ 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},
+ {sdesktop::IRQ_QUEUE_BUFFER_NAME, 1, sdesktop::irq_queue_object_size}});
if (ret == false) {
LOG_ERROR("!!! service-desktop InitHandler failed to initialize worker, service-desktop won't work");
@@ 183,9 186,45 @@ sys::ReturnCodes ServiceDesktop::InitHandler()
return std::make_shared<sys::ResponseMessage>();
});
+ connect(sdesktop::usb::USBConnected(), [&](sys::Message *msg) {
+ if (!desktopWorker->isEndpointSecurityEnabled()) {
+ LOG_INFO("Endpoint security disabled.");
+ return std::make_shared<sys::ResponseMessage>();
+ }
+
+ LOG_INFO("USB connected with endpoint security enabled. Requesting passcode.");
+ desktopWorker->setEndpointSecurity(EndpointSecurity::Block);
+ bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeRequest>(),
+ app::manager::ApplicationManager::ServiceName);
+
+ return std::make_shared<sys::ResponseMessage>();
+ });
+
+ connect(sdesktop::usb::USBDisconnected(), [&](sys::Message *msg) {
+ bus.sendUnicast(std::make_shared<sdesktop::passcode::ScreenPasscodeRequest>(),
+ app::manager::ApplicationManager::ServiceName);
+ return std::make_shared<sys::ResponseMessage>();
+ });
+
+ connect(sdesktop::passcode::ScreenPasscodeUnlocked(), [&](sys::Message *msg) {
+ LOG_INFO("Passcode accepted. Enabling secured endpoints.");
+ desktopWorker->setEndpointSecurity(EndpointSecurity::Allow);
+ return std::make_shared<sys::ResponseMessage>();
+ });
+
settings->registerValueChange(updateos::settings::history,
[this](const std::string &value) { updateOS->setInitialHistory(value); });
+ settings->registerValueChange(
+ ::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);
+ },
+ settings::SettingsScope::Global);
+
return (sys::ReturnCodes::Success);
}
M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +30 -6
@@ 3,6 3,7 @@
#include "service-desktop/ServiceDesktop.hpp"
#include "service-desktop/WorkerDesktop.hpp"
+#include "service-desktop/endpoints/EndpointFactory.hpp"
#include "service-desktop/DesktopMessages.hpp"
#include "parser/MessageHandler.hpp"
#include "parser/ParserFSM.hpp"
@@ 10,27 11,26 @@
#include <bsp/usb/usb.hpp>
#include <log/log.hpp>
-#include <projdefs.h>
-#include <queue.h>
#include <map>
#include <vector>
+#include <module-services/service-desktop/service-desktop/DesktopMessages.hpp>
inline constexpr auto uploadFailedMessage = "file upload terminated before all data transferred";
WorkerDesktop::WorkerDesktop(sys::Service *ownerServicePtr)
: sys::Worker(ownerServicePtr), ownerService(ownerServicePtr), parser(ownerServicePtr), fileDes(nullptr)
-{
-}
+{}
bool WorkerDesktop::init(std::list<sys::WorkerQueueInfo> queues)
{
Worker::init(queues);
- receiveQueue = Worker::getQueueHandleByName(sdesktop::RECEIVE_QUEUE_BUFFER_NAME);
+ irqQueue = Worker::getQueueHandleByName(sdesktop::IRQ_QUEUE_BUFFER_NAME);
+ receiveQueue = Worker::getQueueHandleByName(sdesktop::RECEIVE_QUEUE_BUFFER_NAME);
parserFSM::MessageHandler::setSendQueueHandle(Worker::getQueueHandleByName(sdesktop::SEND_QUEUE_BUFFER_NAME));
- return (bsp::usbInit(receiveQueue, this) < 0) ? false : true;
+ return (bsp::usbInit(receiveQueue, irqQueue, this) < 0) ? false : true;
}
bool WorkerDesktop::deinit(void)
@@ 62,7 62,13 @@ bool WorkerDesktop::handleMessage(uint32_t queueID)
LOG_ERROR("handleMessage failed to receive from \"%s\"", sdesktop::RECEIVE_QUEUE_BUFFER_NAME);
return false;
}
+
+ auto factory = std::make_unique<SecuredEndpointFactory>(endpointSecurity);
+ auto handler = std::make_unique<parserFSM::MessageHandler>(ownerService, std::move(factory));
+
+ parser.setMessageHandler(std::move(handler));
parser.processMessage(std::move(*receivedMsg));
+
delete receivedMsg;
}
else if (qname == sdesktop::SEND_QUEUE_BUFFER_NAME) {
@@ 91,6 97,24 @@ bool WorkerDesktop::handleMessage(uint32_t queueID)
return false;
}
}
+ else if (qname == sdesktop::IRQ_QUEUE_BUFFER_NAME) {
+ bsp::USBDeviceStatus notification = bsp::USBDeviceStatus::Disconnected;
+ if (!queue->Dequeue(¬ification, 0)) {
+ LOG_ERROR("handleMessage xQueueReceive failed for %s.", sdesktop::IRQ_QUEUE_BUFFER_NAME);
+ return false;
+ }
+
+ LOG_DEBUG("USB status: %d", static_cast<int>(notification));
+
+ if (notification == bsp::USBDeviceStatus::Connected) {
+ ownerService->bus.sendUnicast(std::make_shared<sdesktop::usb::USBConnected>(),
+ service::name::service_desktop);
+ }
+ else if (notification == bsp::USBDeviceStatus::Disconnected) {
+ ownerService->bus.sendUnicast(std::make_shared<sdesktop::usb::USBDisconnected>(),
+ service::name::service_desktop);
+ }
+ }
else {
LOG_INFO("handeMessage got message on an unhandled queue");
}
M module-services/service-desktop/endpoints/Endpoint.hpp => module-services/service-desktop/endpoints/Endpoint.hpp +17 -2
@@ 5,6 5,7 @@
#include "Context.hpp"
#include <parser/ParserUtils.hpp>
+#include <parser/MessageHandler.hpp>
#include <json/json11.hpp>
#include <Common/Query.hpp>
@@ 17,10 18,9 @@ namespace parserFSM
class Endpoint
{
-
public:
Endpoint(sys::Service *_ownerServicePtr) : ownerServicePtr(_ownerServicePtr){};
- virtual ~Endpoint() = default;
+ virtual ~Endpoint() = default;
virtual auto handle(parserFSM::Context &context) -> void = 0;
auto c_str() -> const char *
{
@@ 32,4 32,19 @@ namespace parserFSM
sys::Service *ownerServicePtr = nullptr;
};
+ class SecuredEndpoint : public Endpoint
+ {
+ public:
+ explicit SecuredEndpoint(sys::Service *ownerServicePtr) : Endpoint(ownerServicePtr)
+ {}
+ ~SecuredEndpoint() = default;
+
+ auto handle(Context &context) -> void override
+ {
+ context.setResponseStatus(http::Code::Forbidden);
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ LOG_INFO("Endpoint #%d secured", static_cast<int>(context.getEndpoint()));
+ }
+ };
+
} // namespace parserFSM
M module-services/service-desktop/endpoints/EndpointFactory.hpp => module-services/service-desktop/endpoints/EndpointFactory.hpp +36 -1
@@ 23,7 23,8 @@
class EndpointFactory
{
public:
- static auto create(parserFSM::Context &context, sys::Service *ownerServicePtr)
+ virtual ~EndpointFactory() = default;
+ virtual auto create(parserFSM::Context &context, sys::Service *ownerServicePtr)
-> std::unique_ptr<parserFSM::Endpoint>
{
LOG_DEBUG("Creating endpoint: %d", static_cast<int>(context.getEndpoint()));
@@ 57,3 58,37 @@ class EndpointFactory
}
}
};
+
+enum class EndpointSecurity
+{
+ Allow = 0,
+ Block = 1
+};
+
+class SecuredEndpointFactory : public EndpointFactory
+{
+ static constexpr auto Whitelist = {parserFSM::EndpointType::developerMode};
+
+ public:
+ explicit SecuredEndpointFactory(EndpointSecurity security) : endpointSecurity(security)
+ {}
+
+ auto create(parserFSM::Context &context, sys::Service *ownerServicePtr)
+ -> std::unique_ptr<parserFSM::Endpoint> override
+ {
+ auto security = endpointSecurity;
+ if (std::find(Whitelist.begin(), Whitelist.end(), context.getEndpoint()) != Whitelist.end()) {
+ security = EndpointSecurity::Allow;
+ }
+
+ switch (security) {
+ case EndpointSecurity::Allow:
+ return EndpointFactory::create(context, ownerServicePtr);
+ default:
+ return std::make_unique<parserFSM::SecuredEndpoint>(ownerServicePtr);
+ }
+ }
+
+ private:
+ EndpointSecurity endpointSecurity;
+};
M module-services/service-desktop/endpoints/backup/BackupEndpoint.hpp => module-services/service-desktop/endpoints/backup/BackupEndpoint.hpp +1 -2
@@ 1,11 1,10 @@
-// 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
#pragma once
#include <endpoints/Endpoint.hpp>
#include <parser/ParserUtils.hpp>
-#include <service-desktop/ServiceDesktop.hpp>
#include <Service/Common.hpp>
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +13 -2
@@ 103,6 103,17 @@ auto DeveloperModeHelper::processPut(Context &context) -> ProcessResult
service::name::system_manager);
return {sent::delayed, std::nullopt};
}
+ else if (body[json::developerMode::usbSecurity].is_string()) {
+ std::shared_ptr<sys::DataMessage> msg = std::make_shared<sdesktop::usb::USBConnected>();
+ if (body[json::developerMode::usbSecurity].string_value() == json::developerMode::usbUnlock) {
+ 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());
+ }
return {sent::no, endpoint::ResponseContext{.status = code}};
}
@@ 237,8 248,8 @@ auto DeveloperModeHelper::smsRecordFromJson(json11::Json msgJson) -> SMSRecord
record.type = static_cast<SMSType>(msgJson[json::messages::messageType].int_value());
utils::PhoneNumber phoneNumber(msgJson[json::messages::phoneNumber].string_value());
record.number = phoneNumber.getView();
- record.date = utils::time::getCurrentTimestamp().getTime();
- record.body = UTF8(msgJson[json::messages::messageBody].string_value());
+ record.date = utils::time::getCurrentTimestamp().getTime();
+ record.body = UTF8(msgJson[json::messages::messageBody].string_value());
return record;
}
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp +11 -1
@@ 56,6 56,8 @@ namespace parserFSM
inline constexpr auto getInfo = "getInfo";
inline constexpr auto tethering = "tethering";
+ inline constexpr auto tethering = "tethering";
+ inline constexpr auto usbSecurity = "usbSecurity";
/// values for getInfo cmd
inline constexpr auto simStateInfo = "simState";
inline constexpr auto cellularStateInfo = "cellularState";
@@ 66,5 68,13 @@ namespace parserFSM
/// values for tethering
inline constexpr auto tetheringOn = "on";
inline constexpr auto tetheringOff = "off";
- }
+
+ /// values for tethering
+ inline constexpr auto tetheringOn = "on";
+ inline constexpr auto tetheringOff = "off";
+ } // namespace json::developerMode
+
+ /// values for usbSecurity
+ inline constexpr auto usbLock = "usbLock";
+ inline constexpr auto usbUnlock = "usbUnlock";
} // namespace parserFSM
M module-services/service-desktop/endpoints/restore/RestoreEndpoint.hpp => module-services/service-desktop/endpoints/restore/RestoreEndpoint.hpp +3 -2
@@ 1,9 1,10 @@
-// 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
+#pragma once
+
#include <endpoints/Endpoint.hpp>
#include <parser/ParserUtils.hpp>
-#include <service-desktop/ServiceDesktop.hpp>
#include <string>
M module-services/service-desktop/parser/HttpEnums.hpp => module-services/service-desktop/parser/HttpEnums.hpp +1 -0
@@ 14,6 14,7 @@ namespace parserFSM::http
OK = 200,
Accepted = 202,
BadRequest = 400,
+ Forbidden = 403,
NotAcceptable = 406,
InternalServerError = 500
};
M module-services/service-desktop/parser/MessageHandler.cpp => module-services/service-desktop/parser/MessageHandler.cpp +7 -4
@@ 4,7 4,6 @@
#include "MessageHandler.hpp"
#include <endpoints/Context.hpp>
-#include <endpoints/Endpoint.hpp>
#include <endpoints/EndpointFactory.hpp>
#include <FreeRTOS.h>
@@ 23,10 22,14 @@ using namespace parserFSM;
xQueueHandle MessageHandler::sendQueue;
-MessageHandler::MessageHandler(const std::string &message, sys::Service *OwnerService) : OwnerServicePtr(OwnerService)
+MessageHandler::MessageHandler(sys::Service *OwnerService, std::unique_ptr<EndpointFactory> endpointFactory)
+ : OwnerServicePtr(OwnerService), endpointFactory(std::move(endpointFactory))
+{}
+
+void MessageHandler::parseMessage(const std::string &msg)
{
try {
- messageJson = json11::Json::parse(message, JsonErrorMsg);
+ messageJson = json11::Json::parse(msg, JsonErrorMsg);
}
catch (const std::exception &e) {
LOG_ERROR("Cannot create MessageHandler! err:%s", e.what());
@@ 43,7 46,7 @@ void MessageHandler::processMessage()
context->getUuid(),
context->getBody().dump().c_str());
- auto handler = EndpointFactory::create(*context, OwnerServicePtr);
+ auto handler = endpointFactory->create(*context, OwnerServicePtr);
if (handler != nullptr) {
handler->handle(*context);
M module-services/service-desktop/parser/MessageHandler.hpp => module-services/service-desktop/parser/MessageHandler.hpp +6 -2
@@ 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
#pragma once
@@ 20,6 20,8 @@ extern "C"
#include <queue.h>
}
+class EndpointFactory;
+
namespace parserFSM
{
class MessageHandler
@@ 29,9 31,10 @@ namespace parserFSM
json11::Json messageJson;
std::string JsonErrorMsg;
sys::Service *OwnerServicePtr = nullptr;
+ std::unique_ptr<EndpointFactory> endpointFactory;
public:
- MessageHandler(const std::string &message, sys::Service *OwnerService);
+ MessageHandler(sys::Service *OwnerService, std::unique_ptr<EndpointFactory> endpointFactory);
[[nodiscard]] auto isJSONNull() const -> bool
{
@@ 45,6 48,7 @@ namespace parserFSM
{
return JsonErrorMsg;
};
+ void parseMessage(const std::string &msg);
void processMessage();
static void putToSendQueue(const std::string &msg);
static void setSendQueueHandle(xQueueHandle handle)
M module-services/service-desktop/parser/ParserFSM.cpp => module-services/service-desktop/parser/ParserFSM.cpp +10 -6
@@ 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 "MessageHandler.hpp"
@@ 161,14 161,18 @@ void StateMachine::parsePayload()
state = State::ReceivedPayload;
- // processing payload
- auto handler = std::make_unique<MessageHandler>(payload, OwnerServicePtr);
+ messageHandler->parseMessage(payload);
- if (!handler->isValid() || handler->isJSONNull()) {
- LOG_DEBUG("JsonErr: %s", handler->getErrorString().c_str());
+ if (!messageHandler->isValid() || messageHandler->isJSONNull()) {
+ LOG_DEBUG("JsonErr: %s", messageHandler->getErrorString().c_str());
state = State::NoMsg;
return;
}
- handler->processMessage();
+ messageHandler->processMessage();
+}
+
+void StateMachine::setMessageHandler(std::unique_ptr<MessageHandler> handler)
+{
+ messageHandler = std::move(handler);
}
M module-services/service-desktop/parser/ParserFSM.hpp => module-services/service-desktop/parser/ParserFSM.hpp +4 -1
@@ 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
#pragma once
@@ 35,6 35,8 @@ namespace parserFSM
state = newState;
}
+ void setMessageHandler(std::unique_ptr<MessageHandler> handler);
+
private:
std::string receivedMsg;
parserFSM::State state = State::NoMsg;
@@ 42,6 44,7 @@ namespace parserFSM
std::string header;
unsigned long payloadLength = 0;
sys::Service *OwnerServicePtr = nullptr;
+ std::unique_ptr<MessageHandler> messageHandler;
void parseHeader();
void parsePartialHeader();
M module-services/service-desktop/service-desktop/DesktopMessages.hpp => module-services/service-desktop/service-desktop/DesktopMessages.hpp +55 -0
@@ 7,6 7,10 @@
#include <endpoints/bluetooth/BluetoothEndpoint.hpp>
#include <endpoints/update/UpdateMuditaOS.hpp>
+#include <service-appmgr/Actions.hpp>
+#include <service-appmgr/messages/ActionRequest.hpp>
+#include <service-appmgr/data/SimActionsParams.hpp>
+#include <service-appmgr/data/UsbActionsParams.hpp>
#include <Service/Message.hpp>
#include <MessageType.hpp>
#include <service-desktop/DeveloperModeMessage.hpp>
@@ 67,6 71,57 @@ namespace sdesktop
~FactoryMessage() override = default;
};
+ namespace usb
+ {
+ class USBConnected : public sys::DataMessage
+ {
+ public:
+ USBConnected() : sys::DataMessage(MessageType::USBConnected)
+ {}
+ ~USBConnected() override = default;
+ };
+
+ class USBDisconnected : public sys::DataMessage
+ {
+ public:
+ USBDisconnected() : sys::DataMessage(MessageType::USBDisconnected)
+ {}
+ ~USBDisconnected() override = default;
+ };
+
+ } // namespace usb
+
+ namespace passcode
+ {
+ class ScreenPasscodeRequest : public sys::DataMessage, public app::manager::actions::ConvertibleToAction
+ {
+ static constexpr auto passcodeName = "ScreenPasscode";
+
+ public:
+ explicit ScreenPasscodeRequest(bool cancel = false)
+ : sys::DataMessage(MessageType::ScreenPasscodeRequest), cancel(cancel)
+ {}
+
+ [[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest>
+ {
+ return std::make_unique<app::manager::ActionRequest>(
+ sender,
+ app::manager::actions::RequestScreenPasscode,
+ std::make_unique<app::manager::actions::ScreenPasscodeParams>(cancel));
+ }
+
+ private:
+ bool cancel = false;
+ };
+
+ class ScreenPasscodeUnlocked : public sys::DataMessage
+ {
+ public:
+ explicit ScreenPasscodeUnlocked() : sys::DataMessage(MessageType::ScreenPasscodeUnlocked)
+ {}
+ }; // namespace sdesktop
+ } // namespace passcode
+
namespace developerMode
{
M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +4 -1
@@ 22,12 22,15 @@ namespace settings
namespace sdesktop
{
- inline constexpr auto service_stack = 8192;
+ inline constexpr auto service_stack = 8192;
inline constexpr auto cdc_queue_len = 32;
inline constexpr auto cdc_queue_object_size = 1024;
+ inline constexpr auto irq_queue_object_size = sizeof(bsp::USBDeviceStatus);
inline constexpr auto file_transfer_timeout = 5000;
inline constexpr auto RECEIVE_QUEUE_BUFFER_NAME = "receiveQueueBuffer";
inline constexpr auto SEND_QUEUE_BUFFER_NAME = "sendQueueBuffer";
+ inline constexpr auto IRQ_QUEUE_BUFFER_NAME = "irqQueueBuffer";
+
}; // namespace sdesktop
class ServiceDesktop : public sys::Service
M module-services/service-desktop/service-desktop/WorkerDesktop.hpp => module-services/service-desktop/service-desktop/WorkerDesktop.hpp +21 -3
@@ 1,10 1,8 @@
-// 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
#pragma once
-#include <string.h>
-#include <stdio.h>
#include <filesystem>
#include <atomic>
#include "Service/Message.hpp"
@@ 12,6 10,7 @@
#include "Service/Worker.hpp"
#include "Service/Timer.hpp"
#include "parser/ParserFSM.hpp"
+#include "endpoints/EndpointFactory.hpp"
#include "bsp/usb/usb.hpp"
class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
@@ 26,6 25,7 @@ class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
{
CancelTransfer,
};
+
WorkerDesktop(sys::Service *ownerServicePtr);
virtual bool init(std::list<sys::WorkerQueueInfo> queues) override;
@@ 48,6 48,21 @@ 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();
@@ 60,9 75,12 @@ class WorkerDesktop : public sys::Worker, public bsp::USBDeviceListener
bool stateChangeWait();
xQueueHandle receiveQueue;
+ xQueueHandle irqQueue;
FILE *fileDes = nullptr;
uint32_t writeFileSizeExpected = 0;
uint32_t writeFileDataWritten = 0;
std::filesystem::path filePath;
std::atomic<bool> rawModeEnabled = false;
+ bool endpointSecurityEnabled = true;
+ EndpointSecurity endpointSecurity;
};
M module-services/service-desktop/tests/test-contacts.cpp => module-services/service-desktop/tests/test-contacts.cpp +10 -3
@@ 138,11 138,17 @@ bool DBServiceAPI::AddSMS(sys::Service *serv, const SMSRecord &record, std::uniq
}
xQueueHandle parserFSM::MessageHandler::sendQueue;
-parserFSM::MessageHandler::MessageHandler(const std::string &message, sys::Service *OwnerService)
- : OwnerServicePtr(OwnerService)
+
+parserFSM::MessageHandler::MessageHandler(sys::Service *OwnerService, std::unique_ptr<EndpointFactory> endpointFactory)
+ : OwnerServicePtr(OwnerService), endpointFactory(std::move(endpointFactory))
+{}
+
+void parserFSM::MessageHandler::parseMessage(const std::string &msg)
{}
+
void parserFSM::MessageHandler::processMessage()
{}
+
void parserFSM::MessageHandler::putToSendQueue(const std::string &msg)
{
messageStrings.push_back(msg);
@@ 174,7 180,8 @@ TEST_CASE("Endpoint Contacts Test")
REQUIRE(err.empty());
parserFSM::PagedContext context(msgJson, 10);
- auto handler = EndpointFactory::create(context, nullptr);
+ auto factory = std::make_unique<SecuredEndpointFactory>(EndpointSecurity::Allow);
+ auto handler = factory->create(context, nullptr);
handler->handle(context);
auto pageSize = context.getPageSize();
REQUIRE(10 == pageSize);
M module-services/service-desktop/tests/unittest.cpp => module-services/service-desktop/tests/unittest.cpp +37 -3
@@ 25,7 25,6 @@
#include <string>
#include <vector>
-
TEST_CASE("System Update Tests")
{
UpdateMuditaOS updateOS(nullptr);
@@ 49,6 48,10 @@ TEST_CASE("Parser Test")
{
StateMachine parser(nullptr);
+ auto factory = std::make_unique<SecuredEndpointFactory>(EndpointSecurity::Allow);
+ auto handler = std::make_unique<parserFSM::MessageHandler>(nullptr, std::move(factory));
+ parser.setMessageHandler(std::move(handler));
+
SECTION("Parse message with divided header and payload")
{
std::string testMessage("#00000");
@@ 275,7 278,8 @@ TEST_CASE("Endpoint Factory test")
REQUIRE(err.empty());
Context context(msgJson);
- auto handler = EndpointFactory::create(context, nullptr);
+ auto factory = std::make_unique<EndpointFactory>();
+ auto handler = factory->create(context, nullptr);
REQUIRE(dynamic_cast<ContactsEndpoint *>(handler.get()));
}
@@ 287,7 291,37 @@ TEST_CASE("Endpoint Factory test")
REQUIRE(err.empty());
Context context(msgJson);
- auto handler = EndpointFactory::create(context, nullptr);
+ auto factory = std::make_unique<EndpointFactory>();
+ auto handler = factory->create(context, nullptr);
REQUIRE(handler == nullptr);
}
}
+
+TEST_CASE("Secured Endpoint Factory test")
+{
+ SECTION("Allowed endpoint")
+ {
+ auto testMessage = R"({"endpoint":7, "method":1, "uuid":12345, "body":{"test":"test"}})";
+ std::string err;
+ auto msgJson = json11::Json::parse(testMessage, err);
+ REQUIRE(err.empty());
+
+ Context context(msgJson);
+ auto factory = std::make_unique<SecuredEndpointFactory>(EndpointSecurity::Allow);
+ auto handler = factory->create(context, nullptr);
+ REQUIRE(dynamic_cast<ContactsEndpoint *>(handler.get()));
+ }
+
+ SECTION("Secured endpoint")
+ {
+ auto testMessage = R"({"endpoint":25, "method":8, "uuid":"12345", "body":{"te":"test"}})";
+ std::string err;
+ auto msgJson = json11::Json::parse(testMessage, err);
+ REQUIRE(err.empty());
+
+ Context context(msgJson);
+ auto factory = std::make_unique<SecuredEndpointFactory>(EndpointSecurity::Block);
+ auto handler = factory->create(context, nullptr);
+ REQUIRE(dynamic_cast<SecuredEndpoint *>(handler.get()));
+ }
+}
M source/MessageType.hpp => source/MessageType.hpp +7 -0
@@ 215,8 215,15 @@ enum class MessageType
Restore,
Factory,
DeveloperModeRequest,
+ PasscodeRequest,
TransferTimer,
+ USBConnected,
+ USBDisconnected,
+
+ ScreenPasscodeRequest,
+ ScreenPasscodeUnlocked,
+
// FOTA messages
HttpRequest,
HttpResponse,
M test/harness/harness.py => test/harness/harness.py +7 -1
@@ 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
import time
from enum import Enum
@@ 41,6 41,12 @@ class Harness:
def get_application_name(self):
return self.connection.get_application_name()
+ def unlock_usb(self):
+ self.connection.usb_unlock()
+
+ def lock_usb(self):
+ self.connection.usb_lock()
+
def unlock_phone(self):
if self.connection.is_phone_locked():
self.connection.send_key_code(key_codes["enter"])
M test/harness/interface/CDCSerial.py => test/harness/interface/CDCSerial.py +16 -0
@@ 130,6 130,22 @@ class CDCSerial:
ret = self.write(self.__wrap_message(body))
return ret["body"]["isLocked"]
+ def usb_lock(self):
+ body = {
+ "usbSecurity": "usbLock"
+ }
+
+ ret = self.write(self.__wrap_message(body))
+ return ret["status"]
+
+ def usb_unlock(self):
+ body = {
+ "usbSecurity": "usbUnlock"
+ }
+
+ ret = self.write(self.__wrap_message(body))
+ return ret["status"]
+
@staticmethod
def find_Pures() -> str:
'''
M test/harness/interface/defs.py => test/harness/interface/defs.py +1 -0
@@ 28,6 28,7 @@ status = {
"OK": 200,
"Accepted": 202,
"BadRequest": 400,
+ "Forbidden": 403,
"NotAcceptable": 406,
"InternalServerError": 500,
}
M test/pytest/conftest.py => test/pytest/conftest.py +7 -1
@@ 112,7 112,6 @@ def harness(request):
else:
return harness
-
@pytest.fixture(scope='session')
def harnesses():
'''
@@ 130,6 129,13 @@ def phone_unlocked(harness):
harness.unlock_phone()
assert harness.is_phone_unlocked
+@pytest.fixture(scope='session')
+def usb_unlocked(harness):
+ harness.unlock_usb()
+
+@pytest.fixture(scope='session')
+def usb_locked(harness):
+ harness.lock_usb()
@pytest.fixture(scope='session')
def phones_unlocked(harnesses):
M test/pytest/service-desktop/test_backup.py => test/pytest/service-desktop/test_backup.py +1 -0
@@ 5,6 5,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_backup(harness):
body = {"backupReady": True}
ret = harness.endpoint_request("backup", "get", body)
M test/pytest/service-desktop/test_battery_file.py => test/pytest/service-desktop/test_battery_file.py +1 -0
@@ 5,6 5,7 @@ from harness.interface.defs import status
@pytest.mark.rt1051
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_battery_file(harness):
body = {"command" : "checkFile" , "fileName" : "/sys/user/batteryFuelGaugeConfig.cfg"}
ret = harness.endpoint_request("filesystemUpload", "post", body)
M test/pytest/service-desktop/test_bluetooth.py => test/pytest/service-desktop/test_bluetooth.py +2 -0
@@ 9,6 9,7 @@ import time
@pytest.mark.rt1051
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_bluetooth_on_off(harness):
body = {"state": True}
ret = harness.endpoint_request("bluetooth", "get", body)
@@ 38,6 39,7 @@ def test_bluetooth_on_off(harness):
@pytest.mark.rt1051
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_bluetooth_scan(harness):
body = {"state": True}
ret = harness.endpoint_request("bluetooth", "get", body)
M test/pytest/service-desktop/test_calendar.py => test/pytest/service-desktop/test_calendar.py +1 -0
@@ 6,6 6,7 @@ import copy
@pytest.mark.skip("not working on CI")
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_calendar(harness):
# add events
add_body = {
M test/pytest/service-desktop/test_calllog.py => test/pytest/service-desktop/test_calllog.py +1 -0
@@ 5,6 5,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_calllog(harness):
# checking call log count
body = {"count": True}
A test/pytest/service-desktop/test_connection_security.py => test/pytest/service-desktop/test_connection_security.py +40 -0
@@ 0,0 1,40 @@
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+import pytest
+import time
+from harness.interface.defs import status
+from harness import utils, log
+
+@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_locked")
+def test_secured_endpoint(harness):
+ body = {}
+
+ ret = harness.endpoint_request("deviceInfo", "get", body)
+ assert ret["status"] == status["Forbidden"]
+
+ ret = harness.endpoint_request("messages", "get", body)
+ assert ret["status"] == status["Forbidden"]
+
+ ret = harness.endpoint_request("calllog", "get", body)
+ assert ret["status"] == status["Forbidden"]
+
+ ret = harness.endpoint_request("backup", "get", body)
+ assert ret["status"] == status["Forbidden"]
+
+ ret = harness.endpoint_request("contacts", "get", body)
+ assert ret["status"] == status["Forbidden"]
+
+ harness.unlock_usb()
+
+ ret = harness.endpoint_request("deviceInfo", "get", body)
+ assert ret["status"] == status["OK"]
+
+ ret = harness.endpoint_request("calllog", "get", body)
+ assert ret["status"] == status["OK"]
+
+ ret = harness.endpoint_request("backup", "get", body)
+ assert ret["status"] == status["OK"]
+
+ ret = harness.endpoint_request("contacts", "get", body)
+ assert ret["status"] == status["OK"]<
\ No newline at end of file
M test/pytest/service-desktop/test_contacts.py => test/pytest/service-desktop/test_contacts.py +1 -0
@@ 5,6 5,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_contacts(harness):
# getting the contacts count
body = {"limit": True}
M test/pytest/service-desktop/test_device_info.py => test/pytest/service-desktop/test_device_info.py +1 -0
@@ 4,6 4,7 @@ import pytest
from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_device_info(harness):
body = {}
ret = harness.endpoint_request("deviceInfo", "get", body)
M test/pytest/service-desktop/test_factory_reset.py => test/pytest/service-desktop/test_factory_reset.py +1 -0
@@ 6,6 6,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
@pytest.mark.skip(reason="This will make a factory reset")
+@pytest.mark.usefixtures("usb_unlocked")
def test_factory_reset(harness):
body = {"factoryRequest": True}
ret = harness.endpoint_request("factory", "post", body)
M test/pytest/service-desktop/test_messages.py => test/pytest/service-desktop/test_messages.py +1 -0
@@ 6,6 6,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_messages(harness):
# getting the messages count
body = {"category": "message", "count": True}
M test/pytest/service-desktop/test_templates.py => test/pytest/service-desktop/test_templates.py +1 -0
@@ 5,6 5,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_templates(harness):
# getting the templates count
body = {"category": "template", "count": True}
M test/pytest/service-desktop/test_threads.py => test/pytest/service-desktop/test_threads.py +1 -0
@@ 5,6 5,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_threads(harness):
# getting all threads
body = {"category": "thread"}
M test/pytest/service-desktop/test_update.py => test/pytest/service-desktop/test_update.py +1 -0
@@ 5,6 5,7 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
+@pytest.mark.usefixtures("usb_unlocked")
def test_update(harness):
body = {}
ret = harness.endpoint_request("update", "get", body)