hpcstat/src/ssh.cpp

89 lines
2.6 KiB
C++
Raw Permalink Normal View History

2024-05-03 16:15:40 +08:00
# include <filesystem>
# include <iostream>
# include <regex>
# include <hpcstat/ssh.hpp>
# include <hpcstat/keys.hpp>
# include <hpcstat/env.hpp>
# include <hpcstat/common.hpp>
# include <fmt/format.h>
# include <boost/filesystem.hpp>
# include <boost/process.hpp>
# include <boost/dll.hpp>
namespace hpcstat::ssh
{
std::optional<std::string> fingerprint()
{
2024-05-04 15:38:56 +08:00
if (auto sshbindir = env::env("HPCSTAT_SSH_BINDIR"); !sshbindir)
2024-05-03 16:15:40 +08:00
return std::nullopt;
else if
(
auto output =
2024-05-04 15:38:56 +08:00
exec(std::filesystem::path(*sshbindir) / "ssh-add", { "-l" });
2024-05-03 16:15:40 +08:00
!output
)
{ std::cerr << "Failed to get ssh fingerprints\n"; return std::nullopt; }
else
{
std::regex pattern(R"r(\b(?:sha|SHA)256:([0-9A-Za-z+/=]{43})\b)r");
std::smatch match;
for
(
auto i = std::sregex_iterator(output->begin(), output->end(), pattern);
2024-05-04 11:57:13 +08:00
i != std::sregex_iterator(); ++i
2024-05-03 16:15:40 +08:00
)
if (Keys.contains(i->str(1))) return i->str(1);
std::cerr << fmt::format("No valid fingerprint found in:\n{}\n", *output);
return std::nullopt;
}
}
std::optional<std::string> sign(std::string message, std::string fingerprint)
{
2024-05-04 15:38:56 +08:00
if (auto sshbindir = env::env("HPCSTAT_SSH_BINDIR"); !sshbindir)
return std::nullopt;
else if (auto sharedir = env::env("HPCSTAT_SHAREDIR", true); !sharedir)
2024-05-03 16:15:40 +08:00
return std::nullopt;
else if
(
auto output = exec
(
2024-05-04 15:38:56 +08:00
std::filesystem::path(*sshbindir) / "ssh-keygen",
2024-05-03 16:15:40 +08:00
{
2024-05-03 18:47:37 +08:00
"-Y", "sign", "-q",
2024-05-04 12:22:41 +08:00
"-f", fmt::format("{}/keys/{}", *sharedir, Keys[fingerprint].PubkeyFilename),
2024-05-03 16:15:40 +08:00
"-n", "hpcstat@chn.moe", "-"
},
message
);
!output
)
{ std::cerr << fmt::format("Failed to sign message: {}\n", message); return std::nullopt; }
else return *output;
}
bool verify(std::string message, std::string signature, std::string fingerprint)
{
2024-05-04 15:38:56 +08:00
if (auto sshbindir = env::env("HPCSTAT_SSH_BINDIR"); !sshbindir)
return false;
else if (auto sharedir = env::env("HPCSTAT_SHAREDIR", true); !sharedir)
2024-05-03 16:15:40 +08:00
return false;
else
{
namespace bf = boost::filesystem;
auto tempdir = bf::temp_directory_path() / bf::unique_path();
bf::create_directories(tempdir);
auto signaturefile = tempdir / "signature";
std::ofstream(signaturefile) << signature;
return exec
(
2024-05-04 15:38:56 +08:00
std::filesystem::path(*sshbindir) / "ssh-keygen",
2024-05-03 16:15:40 +08:00
{
"-Y", "verify",
2024-05-04 12:22:41 +08:00
"-f", fmt::format("{}/keys/{}", *sharedir, Keys[fingerprint].PubkeyFilename),
2024-05-03 16:15:40 +08:00
"-n", "hpcstat@chn.moe", "-s", signaturefile.string()
},
message
).has_value();
}
}
}