Browse Source

OUT-893 Local provisioning first working version

OUT-893
Alex Sualdea 1 week ago
parent
commit
a4d3038a12
9 changed files with 215 additions and 121 deletions
  1. +151
    -7
      LocalProvisioning.cpp
  2. +30
    -98
      LocalProvisioning.h
  3. +1
    -4
      pEpCOMServerAdapter.cpp
  4. +12
    -6
      pEpCOMServerAdapter.vcxproj
  5. +1
    -1
      pEpCOMServerAdapter.vcxproj.filters
  6. +12
    -1
      pEp_utility.cpp
  7. +2
    -2
      pEp_utility.h
  8. +3
    -0
      packages.config
  9. +3
    -2
      unpack.cc

+ 151
- 7
LocalProvisioning.cpp View File

@ -6,15 +6,159 @@
namespace pEp
{
void init_provisioning_log();
void LocalProvisioning::Run()
{
init_provisioning_log();
pEp::utility::RegistryKey provisionRegKey(ProvisioningRegKey);
std::wstring isProvisioned = provisionRegKey.GetValue(ProvisioningIsProvisionedRegKey,
L"False");
std::wstring localFolder = provisionRegKey.GetValue(ProvisioningLocalFolderRegKey,
defaultProvisioningPath());
std::wstring provisioning_file_name = provisionRegKey.GetValue(ProvisioningFileNameRegKey,
DefaultProvisionPackage);
if (!convert_bool(isProvisioned))
{
std::filesystem::path pep_user_path(SignedPackage::pEp_locations.at("PER_USER_DIRECTORY"));
std::filesystem::path provisioning_path(localFolder);
std::filesystem::path pkg_path(provisioning_path / provisioning_file_name);
std::filesystem::path deployment_key_path = provisioning_path / DeploymentKeyFile;
std::filesystem::path provisioning_key_path = provisioning_path / ProvisioningKeyFile;
std::filesystem::path target_path = provisioning_path / L"package";
if (!std::filesystem::exists(provisioning_path))
create_dir_if_not_exists(provisioning_path);
if (!std::filesystem::exists(pkg_path)) // there is no package to provision
return;
if (!std::filesystem::exists(deployment_key_path)) // there is no deployment key
{
provisioning_log_info << "Provisioning package found but no deployment key is present.";
return;
}
if (!std::filesystem::exists(provisioning_key_path)) // there is no provisioning key
{
provisioning_log_info << "Provisioning package found but no provisioning key is present.";
return;
}
provisioning_log_info << "Starting Provisioning";
CryptoPP::ed25519PublicKey deployment_key;
CryptoPP::RSA::PrivateKey provisioning_key;
try
{
SignedPackage::LoadPublicKey(deployment_key_path, deployment_key);
SignedPackage::LoadPrivateKey(provisioning_key_path, provisioning_key);
// verify package signature and extract it in a temporary folder and copy them
// to package extraction directory (pep_user_dir\Provisioning\package)
SignedPackage::install_if_location_empty(deployment_key, provisioning_key,
pkg_path, "package", target_path);
// move dbs from package directory into (pEp) user directory
for (auto const& direntry : std::filesystem::directory_iterator{ target_path }) {
std::filesystem::path source = direntry.path();
std::filesystem::rename(direntry.path(), pep_user_path / source.filename());
}
// remove provisioning package and extraction directory
std::filesystem::remove(pkg_path);
std::filesystem::remove(target_path);
provisionRegKey.SetValue(ProvisioningIsProvisionedRegKey, L"True");
provisioning_log_info << "Provisioning has finished succesfully.";
}
catch (std::runtime_error& e)
{
provisioning_log_error << "Provisioning failed: " << e.what();
}
catch (std::exception& e)
{
provisioning_log_error << "Provisioning failed: " << e.what();
}
}
}
bool LocalProvisioning::create_dir_if_not_exists(const std::filesystem::path& path)
{
if (!std::filesystem::exists(path))
{
std::filesystem::create_directories(path);
}
else
{
if (!std::filesystem::is_directory(path))
{
std::filesystem::remove(path);
std::filesystem::create_directories(path);
}
}
return std::filesystem::exists(path) && std::filesystem::is_directory(path);
}
bool LocalProvisioning::convert_bool(const std::wstring& in)
{
bool ret;
if (in.size() < 1)
return false;
std::wstring s = in;
boost::to_lower(s);
std::wistringstream(s) >> std::boolalpha >> ret;
return ret;
}
std::wstring LocalProvisioning::defaultProvisioningPath()
{
std::wstring pep_user_path = SignedPackage::pEp_locations.at("PER_USER_DIRECTORY");
std::filesystem::path provisioning_path(pep_user_path);
provisioning_path /= "Provisioning";
return provisioning_path.c_str();
}
//void install_if_location_empty(
// CryptoPP::PublicKey& deployment_key,
// CryptoPP::PrivateKey& provisioning_key,
// std::filesystem::path pkg_path,
// std::string location,
// std::filesystem::path target_path
//);
void init_provisioning_log()
{
static bool initialized = false;
if (initialized)
return;
static const std::string COMMON_FMT("[%TimeStamp%][%Function%]: %Message%");
boost::log::register_simple_formatter_factory< boost::log::trivial::severity_level, char >("Severity");
// Output message to file, rotates when file reached 1mb or at midnight every day. Each log file
// is capped at 1mb and total is 20mb
boost::filesystem::path user_dir(SignedPackage::pEp_locations.at("PER_USER_DIRECTORY"));
boost::filesystem::path log_path = user_dir / "Logs" / "provisioning_log%3N.txt";
boost::log::add_file_log(
boost::log::keywords::file_name = log_path.c_str(),
boost::log::keywords::rotation_size = 1 * 1024 * 1024,
boost::log::keywords::max_size = 20 * 1024 * 1024,
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
boost::log::keywords::format = COMMON_FMT,
boost::log::keywords::auto_flush = true
);
boost::log::add_common_attributes();
// Only output message with INFO or higher severity in Release
#ifndef _DEBUG
boost::log::core::get()->set_filter(
boost::log::trivial::severity >= boost::log::trivial::info
);
#endif
initialized = true;
}
} // namespaece pEp

+ 30
- 98
LocalProvisioning.h View File

@ -2,6 +2,9 @@
#include "stdafx.h"
#include <boost/algorithm/string.hpp>
#include "unpack.hh"
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup.hpp>
#include <boost/log/utility/manipulators.hpp>
namespace pEp
{
@ -18,109 +21,38 @@ namespace pEp
class LocalProvisioning
{
bool convert_bool(const std::wstring& in)
{
bool ret;
if (in.size() < 1)
return false;
std::wstring s = in;
boost::to_lower(s);
std::wistringstream(s) >> std::boolalpha >> ret;
return ret;
}
std::wstring defaultProvisioningPath()
{
std::wstring pep_user_path = SignedPackage::pEp_locations.at("PER_USER_DIRECTORY");
std::filesystem::path provisioning_path(pep_user_path);
provisioning_path /= "Provisioning";
return provisioning_path.c_str();
}
bool create_dir_if_not_exists(const std::filesystem::path& path)
{
if (!std::filesystem::exists(path))
{
std::filesystem::create_directories(path);
}
else
{
if (!std::filesystem::is_directory(path))
{
std::filesystem::remove(path);
std::filesystem::create_directories(path);
}
}
return std::filesystem::exists(path) && std::filesystem::is_directory(path);
}
/// <summary>
/// Convert string into boolean
/// </summary>
/// <param name="in"></param>
/// <returns></returns>
bool convert_bool(const std::wstring& in);
/// <summary>
/// Get default provisioning directory
/// </summary>
/// <returns></returns>
std::wstring defaultProvisioningPath();
bool create_dir_if_not_exists(const std::filesystem::path& path);
public:
void Run()
{
pEp::utility::RegistryKey provisionRegKey(ProvisioningRegKey);
std::wstring isProvisioned = provisionRegKey.GetValue(ProvisioningIsProvisionedRegKey,
L"False");
std::wstring localFolder = provisionRegKey.GetValue(ProvisioningLocalFolderRegKey,
defaultProvisioningPath());
std::wstring provisioning_file_name = provisionRegKey.GetValue(ProvisioningFileNameRegKey,
DefaultProvisionPackage);
if (!convert_bool(isProvisioned))
{
std::filesystem::path pep_user_path(SignedPackage::pEp_locations.at("PER_USER_DIRECTORY"));
std::filesystem::path provisioning_path(localFolder);
std::filesystem::path pkg_path(provisioning_path / provisioning_file_name);
std::filesystem::path deployment_key_path = provisioning_path / DeploymentKeyFile;
std::filesystem::path provisioning_key_path = provisioning_path / ProvisioningKeyFile;
std::filesystem::path target_path = provisioning_path / L"package";
if (!std::filesystem::exists(provisioning_path))
create_dir_if_not_exists(provisioning_path);
if (!std::filesystem::exists(pkg_path))
return; // AQUI log?
if (!std::filesystem::exists(deployment_key_path))
return; // AQUI log
if (!std::filesystem::exists(provisioning_key_path))
return; // AQUI log
CryptoPP::ed25519PublicKey deployment_key;
CryptoPP::RSA::PrivateKey provisioning_key;
try
{
SignedPackage::LoadPublicKey(deployment_key_path, deployment_key);
SignedPackage::LoadPrivateKey(provisioning_key_path, provisioning_key);
SignedPackage::install_if_location_empty(deployment_key, provisioning_key,
pkg_path, "PER_USER_DIRECTORY", target_path);
for (auto const& direntry : std::filesystem::directory_iterator{ target_path }) {
std::filesystem::path source = direntry.path();
std::filesystem::rename(direntry.path(), pep_user_path / source.filename());
}
provisionRegKey.SetValue(ProvisioningIsProvisionedRegKey,L"True");
}
catch (std::runtime_error& e)
{
std::cout << e.what() << "\n";
}
catch (std::exception& e)
{
std::cout << e.what() << "\n";
}
}
}
/// <summary>
/// Run provisioning procedure
/// </summary>
void Run();
};
/// Provisioning Log
#define LOG_LOCATION(LEVEL) \
BOOST_LOG_SEV(::boost::log::trivial::logger::get(), LEVEL) \
<< boost::log::add_value("Line", __LINE__) \
<< boost::log::add_value("File", __FILE__) \
<< boost::log::add_value("Function", __FUNCTION__) \
#define provisioning_log_debug LOG_LOCATION(::boost::log::trivial::debug)
#define provisioning_log_info BOOST_LOG_TRIVIAL(info)
#define provisioning_log_warning BOOST_LOG_TRIVIAL(warning)
#define provisioning_log_error BOOST_LOG_TRIVIAL(error)


+ 1
- 4
pEpCOMServerAdapter.cpp View File

@ -92,13 +92,10 @@ extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/
_AtlModule.hModule(hInstance);
_AtlModule.start_gatekeeper();
// AQUI provisioning
// Provisioning
pEp::LocalProvisioning provisioning;
provisioning.Run();
// AQUI provisioning
PEP_SESSION first_session;
PEP_STATUS status = ::init(&first_session, NULL, NULL, pEp::Adapter::_ensure_passphrase);


+ 12
- 6
pEpCOMServerAdapter.vcxproj View File

@ -223,23 +223,29 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\boost.1.72.0.0\build\boost.targets" Condition="Exists('..\packages\boost.1.72.0.0\build\boost.targets')" />
<Import Project="..\packages\boost_atomic-vc142.1.72.0.0\build\boost_atomic-vc142.targets" Condition="Exists('..\packages\boost_atomic-vc142.1.72.0.0\build\boost_atomic-vc142.targets')" />
<Import Project="..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets" Condition="Exists('..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets')" />
<Import Project="..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets" Condition="Exists('..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets')" />
<Import Project="..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets" Condition="Exists('..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets')" />
<Import Project="..\packages\boost_filesystem-vc142.1.72.0.0\build\boost_filesystem-vc142.targets" Condition="Exists('..\packages\boost_filesystem-vc142.1.72.0.0\build\boost_filesystem-vc142.targets')" />
<Import Project="..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets" Condition="Exists('..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets')" />
<Import Project="..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets" Condition="Exists('..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets')" />
<Import Project="..\packages\boost_log-vc142.1.72.0.0\build\boost_log-vc142.targets" Condition="Exists('..\packages\boost_log-vc142.1.72.0.0\build\boost_log-vc142.targets')" />
<Import Project="..\packages\boost_log_setup-vc142.1.72.0.0\build\boost_log_setup-vc142.targets" Condition="Exists('..\packages\boost_log_setup-vc142.1.72.0.0\build\boost_log_setup-vc142.targets')" />
<Import Project="..\packages\boost_program_options-vc142.1.72.0.0\build\boost_program_options-vc142.targets" Condition="Exists('..\packages\boost_program_options-vc142.1.72.0.0\build\boost_program_options-vc142.targets')" />
<Import Project="..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets" Condition="Exists('..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets')" />
<Import Project="..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets" Condition="Exists('..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\boost.1.72.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost.1.72.0.0\build\boost.targets'))" />
<Error Condition="!Exists('..\packages\boost_atomic-vc142.1.72.0.0\build\boost_atomic-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_atomic-vc142.1.72.0.0\build\boost_atomic-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_date_time-vc142.1.72.0.0\build\boost_date_time-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_filesystem-vc142.1.72.0.0\build\boost_filesystem-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_filesystem-vc142.1.72.0.0\build\boost_filesystem-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_chrono-vc142.1.72.0.0\build\boost_chrono-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_log-vc142.1.72.0.0\build\boost_log-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_log-vc142.1.72.0.0\build\boost_log-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_log_setup-vc142.1.72.0.0\build\boost_log_setup-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_log_setup-vc142.1.72.0.0\build\boost_log_setup-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_program_options-vc142.1.72.0.0\build\boost_program_options-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_program_options-vc142.1.72.0.0\build\boost_program_options-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets'))" />
<Error Condition="!Exists('..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost_thread-vc142.1.72.0.0\build\boost_thread-vc142.targets'))" />
</Target>
</Project>

+ 1
- 1
pEpCOMServerAdapter.vcxproj.filters View File

@ -122,8 +122,8 @@
<None Include="updatekey.bin">
<Filter>Resource Files</Filter>
</None>
<None Include="packages.config" />
<None Include="pep_test.snk" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Midl Include="pEpCOMServerAdapter.idl">


+ 12
- 1
pEp_utility.cpp View File

@ -603,8 +603,10 @@ namespace pEp {
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkKey, NULL);
}
RegistryKey::RegistryKey(const std::wstring& keyPath) noexcept
RegistryKey::RegistryKey(const std::wstring& keyPath) noexcept :
cu(nullptr), hkKeyPath(nullptr)
{
LONG lResult;
key_path = keyPath;
if (RegOpenCurrentUser(KEY_ALL_ACCESS, &cu) == ERROR_SUCCESS)
{
@ -621,8 +623,17 @@ namespace pEp {
}
}
RegistryKey::~RegistryKey() noexcept
{
if (cu != nullptr)
RegCloseKey(cu);
if (hkKeyPath != nullptr)
RegCloseKey(hkKeyPath);
}
std::wstring RegistryKey::GetValue(const std::wstring& key, const std::wstring& default_value) noexcept
{
LONG lResult;
if (opened)
{
DWORD size;


+ 2
- 2
pEp_utility.h View File

@ -98,8 +98,7 @@ namespace pEp {
{
HKEY cu;
bool opened = false;
HKEY hkKeyPath = NULL;
LONG lResult;
HKEY hkKeyPath;
std::wstring key_path;
LONG create_key(HKEY hk, const std::wstring& key, HKEY& hkKey) noexcept;
@ -111,6 +110,7 @@ namespace pEp {
/// </summary>
/// <param name="keyPath">Key were the settings are to be used (e.g."Software\\pEp\\Something")</param>
RegistryKey(const std::wstring& keyPath) noexcept;
~RegistryKey() noexcept;
/// <summary>
/// Gets a value from a key.


+ 3
- 0
packages.config View File

@ -1,9 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="boost" version="1.72.0.0" targetFramework="native" />
<package id="boost_atomic-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_chrono-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_date_time-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_filesystem-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_log_setup-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_log-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_program_options-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_regex-vc142" version="1.72.0.0" targetFramework="native" />
<package id="boost_thread-vc142" version="1.72.0.0" targetFramework="native" />

+ 3
- 2
unpack.cc View File

@ -193,7 +193,7 @@ namespace SignedPackage {
bool valid = verifier.VerifyStream(_archive,
(unsigned char*) signature, size);
if (!valid)
throw std::runtime_error("signature does not match"); // AQUI
throw std::runtime_error("signature does not match");
}
std::filesystem::path decrypt_distribution_archive(
@ -257,7 +257,8 @@ namespace SignedPackage {
decrypt_distribution_archive(tmp_path / "DIST.A",
tmp_path / "DIST.KEY", provisioning_key);
extract_archive(decrypted_archive, tmp_path);
ensure_target_path(tmp_path / location);
extract_archive(decrypted_archive, tmp_path / location);
ensure_target_path(target_path);
for (auto const& direntry : std::filesystem::directory_iterator{tmp_path / location}) {


Loading…
Cancel
Save