summaryrefslogtreecommitdiff
path: root/virtual-media/src/state_machine.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'virtual-media/src/state_machine.hpp')
-rw-r--r--virtual-media/src/state_machine.hpp102
1 files changed, 90 insertions, 12 deletions
diff --git a/virtual-media/src/state_machine.hpp b/virtual-media/src/state_machine.hpp
index 9cba565..a788043 100644
--- a/virtual-media/src/state_machine.hpp
+++ b/virtual-media/src/state_machine.hpp
@@ -4,6 +4,7 @@
#include "logger.hpp"
#include "smb.hpp"
#include "system.hpp"
+#include "utils.hpp"
#include <sys/mount.h>
@@ -455,15 +456,68 @@ struct MountPointStateMachine
// Mount specialization
if (isLegacy)
{
+ using sdbusplus::message::unix_fd;
+ using optional_fd = std::variant<int, unix_fd>;
+
iface->register_method(
- "Mount", [& machine = state.machine, this,
- handleMount](boost::asio::yield_context yield,
- std::string imgUrl, bool rw) {
+ "Mount", [& machine = state.machine, this, handleMount](
+ boost::asio::yield_context yield,
+ std::string imgUrl, bool rw, optional_fd fd) {
LogMsg(Logger::Info, "[App]: Mount called on ",
getObjectPath(machine), machine.name);
machine.target = {imgUrl, rw};
- return handleMount(yield, machine);
+
+ if (std::holds_alternative<unix_fd>(fd))
+ {
+ LogMsg(Logger::Debug, "[App] Extra data available");
+
+ // Open pipe and prepare output buffer
+ boost::asio::posix::stream_descriptor secretPipe(
+ machine.ioc.get(),
+ dup(std::get<unix_fd>(fd).fd));
+ std::array<char, utils::secretLimit> buf;
+
+ // Read data
+ auto size = secretPipe.async_read_some(
+ boost::asio::buffer(buf), yield);
+
+ // Validate number of NULL delimiters, ensures
+ // further operations are safe
+ auto nullCount = std::count(
+ buf.begin(), buf.begin() + size, '\0');
+ if (nullCount != 2)
+ {
+ throw sdbusplus::exception::SdBusError(
+ EINVAL, "Malformed extra data");
+ }
+
+ // First 'part' of payload
+ std::string user(buf.begin());
+ // Second 'part', after NULL delimiter
+ std::string pass(buf.begin() + user.length() + 1);
+
+ // Encapsulate credentials into safe buffer
+ machine.target->credentials =
+ std::make_unique<utils::CredentialsProvider>(
+ std::move(user), std::move(pass));
+
+ // Cover the tracks
+ utils::secureCleanup(buf);
+ }
+
+ try
+ {
+ auto ret = handleMount(yield, machine);
+ machine.target->credentials.reset();
+ return ret;
+ }
+ catch (...)
+ {
+ machine.target->credentials.reset();
+ throw;
+ return false;
+ }
});
}
else
@@ -644,7 +698,8 @@ struct MountPointStateMachine
"\n Remote parent: ", remoteParent,
"\n Local file: ", localFile);
- if (!smb.mount(remoteParent, state.machine.target->rw))
+ if (!smb.mount(remoteParent, state.machine.target->rw,
+ state.machine.target->credentials))
{
fs::remove_all(*mountDir);
return ReadyState(state, std::errc::invalid_argument,
@@ -684,6 +739,7 @@ struct MountPointStateMachine
static std::shared_ptr<Process>
spawnNbdKit(MountPointStateMachine& machine,
+ std::unique_ptr<utils::VolatileFile>&& secret,
const std::vector<std::string>& params)
{
// Investigate
@@ -740,7 +796,8 @@ struct MountPointStateMachine
args.insert(args.end(), params.begin(), params.end());
if (!process->spawn(
- args, [& machine = machine](int exitCode, bool isReady) {
+ args, [& machine = machine, secret = std::move(secret)](
+ int exitCode, bool isReady) {
LogMsg(Logger::Info, machine.name, " process ended.");
machine.emitSubprocessStoppedEvent();
}))
@@ -756,24 +813,43 @@ struct MountPointStateMachine
static std::shared_ptr<Process>
spawnNbdKit(MountPointStateMachine& machine, const fs::path& file)
{
- return spawnNbdKit(machine, {// Use file plugin ...
- "file",
- // ... to mount file at this location
- "file=" + file.string()});
+ return spawnNbdKit(machine, {},
+ {// Use file plugin ...
+ "file",
+ // ... to mount file at this location
+ "file=" + file.string()});
}
static std::shared_ptr<Process>
spawnNbdKit(MountPointStateMachine& machine, const std::string& url)
{
+ std::unique_ptr<utils::VolatileFile> secret;
std::vector<std::string> params = {
// Use curl plugin ...
"curl",
// ... to mount http resource at url
"url=" + url};
- // TODO: Authorization support in future patch
+ // Authenticate if needed
+ if (machine.target->credentials)
+ {
+ // Pack password into buffer
+ utils::CredentialsProvider::SecureBuffer buff =
+ machine.target->credentials->pack(
+ [](const std::string& user, const std::string& pass,
+ std::vector<char>& buff) {
+ std::copy(pass.begin(), pass.end(),
+ std::back_inserter(buff));
+ });
+
+ // Prepare file to provide the password with
+ secret = std::make_unique<utils::VolatileFile>(std::move(buff));
+
+ params.push_back("user=" + machine.target->credentials->user());
+ params.push_back("password=+" + secret->path());
+ }
- return spawnNbdKit(machine, params);
+ return spawnNbdKit(machine, std::move(secret), params);
}
bool checkUrl(const std::string& urlScheme, const std::string& imageUrl)
@@ -939,6 +1015,7 @@ struct MountPointStateMachine
name = std::move(machine.name);
ioc = machine.ioc;
config = std::move(machine.config);
+ target = std::move(machine.target);
}
return *this;
}
@@ -999,6 +1076,7 @@ struct MountPointStateMachine
std::string imgUrl;
bool rw;
std::optional<fs::path> mountDir;
+ std::unique_ptr<utils::CredentialsProvider> credentials;
};
std::reference_wrapper<boost::asio::io_context> ioc;