OUT-893 Local provisioning first version (incomplete)
parent
300cbe221e
commit
cfcd147e34
|
@ -0,0 +1,20 @@
|
|||
#include "stdafx.h"
|
||||
#include "unpack.hh"
|
||||
#include "LocalProvisioning.h"
|
||||
|
||||
|
||||
namespace pEp
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//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
|
||||
//);
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "unpack.hh"
|
||||
|
||||
namespace pEp
|
||||
{
|
||||
|
||||
#define ProvisioningRegKey _T("Software\\pEp\\Provisioning")
|
||||
#define ProvisioningLocalFolderRegKey _T("LocalFolder")
|
||||
#define ProvisioningIsProvisionedRegKey _T("IsProvisioned")
|
||||
#define ProvisioningFileNameRegKey _T("FileName")
|
||||
|
||||
#define DeploymentKeyFile L"deployment_key-pub.der"
|
||||
#define ProvisioningKeyFile L"provisioning_key.der"
|
||||
#define DefaultProvisionPackage L"pEp.pkk"
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#include "pEpCOMServerAdapter.h"
|
||||
#include "LocalJSONAdapter.h"
|
||||
#include "CMainWindow.h"
|
||||
#include "LocalProvisioning.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -91,6 +92,13 @@ extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/
|
|||
_AtlModule.hModule(hInstance);
|
||||
_AtlModule.start_gatekeeper();
|
||||
|
||||
// AQUI provisioning
|
||||
|
||||
pEp::LocalProvisioning provisioning;
|
||||
provisioning.Run();
|
||||
|
||||
// AQUI provisioning
|
||||
|
||||
PEP_SESSION first_session;
|
||||
PEP_STATUS status = ::init(&first_session, NULL, NULL, pEp::Adapter::_ensure_passphrase);
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<PreprocessorDefinitions>JSON_ADAPTER_LIBRARY;DEBUG_ENABLED;WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
|
@ -109,6 +110,7 @@
|
|||
<PreprocessorDefinitions>JSON_ADAPTER_LIBRARY;DEBUG_ENABLED;WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Midl>
|
||||
<MkTypLibCompatible>false</MkTypLibCompatible>
|
||||
|
@ -151,10 +153,12 @@
|
|||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pEp_utility.cpp" />
|
||||
<ClCompile Include="LocalProvisioning.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="unpack.cc" />
|
||||
<ClCompile Include="utf8_helper.cpp" />
|
||||
<ClCompile Include="xdlldata.c">
|
||||
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
|
||||
|
@ -171,12 +175,14 @@
|
|||
<ClInclude Include="CpEpEngine.h" />
|
||||
<ClInclude Include="GateKeeper.h" />
|
||||
<ClInclude Include="LocalJSONAdapter.h" />
|
||||
<ClInclude Include="LocalProvisioning.h" />
|
||||
<ClInclude Include="pEpCOMServerAdapter.h" />
|
||||
<ClInclude Include="pEpCOMServerAdapter_i.h" />
|
||||
<ClInclude Include="pEp_utility.h" />
|
||||
<ClInclude Include="Resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="unpack.hh" />
|
||||
<ClInclude Include="utf8_helper.h" />
|
||||
<ClInclude Include="xdlldata.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -49,6 +49,12 @@
|
|||
<ClCompile Include="CMainWindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="unpack.cc">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LocalProvisioning.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
|
@ -90,6 +96,12 @@
|
|||
<ClInclude Include="CMainWindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="unpack.hh">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LocalProvisioning.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="pEpCOMServerAdapter.rc">
|
||||
|
|
|
@ -594,5 +594,70 @@ namespace pEp {
|
|||
*opt_field_array = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** RegistryKey class **/
|
||||
|
||||
LONG RegistryKey::create_key(HKEY hk, const std::wstring& key, HKEY& hkKey) noexcept
|
||||
{
|
||||
return RegCreateKeyEx(hk, key.c_str(), 0, REG_NONE,
|
||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkKey, NULL);
|
||||
}
|
||||
|
||||
RegistryKey::RegistryKey(const std::wstring& keyPath) noexcept
|
||||
{
|
||||
key_path = keyPath;
|
||||
if (RegOpenCurrentUser(KEY_ALL_ACCESS, &cu) == ERROR_SUCCESS)
|
||||
{
|
||||
lResult = RegOpenKeyEx(cu, key_path.c_str(), 0, KEY_ALL_ACCESS, &hkKeyPath);
|
||||
if (lResult == ERROR_SUCCESS)
|
||||
{
|
||||
opened = true;
|
||||
}
|
||||
else if (lResult == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
if (create_key(cu, key_path, hkKeyPath) == ERROR_SUCCESS)
|
||||
opened = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring RegistryKey::GetValue(const std::wstring& key, const std::wstring& default_value) noexcept
|
||||
{
|
||||
if (opened)
|
||||
{
|
||||
DWORD size;
|
||||
lResult = RegGetValue(cu, key_path.c_str(), key.c_str(), RRF_RT_REG_SZ, NULL, NULL, &size);
|
||||
if (lResult == ERROR_SUCCESS && size)
|
||||
{
|
||||
std::wstring ret;
|
||||
std::unique_ptr<wchar_t[]> value(new wchar_t[size]);
|
||||
lResult = RegGetValue(cu, key_path.c_str(), key.c_str(), RRF_RT_REG_SZ, NULL, value.get(), &size);
|
||||
ret = value.get();
|
||||
if (lResult == ERROR_SUCCESS)
|
||||
return ret;
|
||||
else
|
||||
return default_value;
|
||||
}
|
||||
else if (lResult == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
SetValue(key, default_value);
|
||||
return default_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
bool RegistryKey::SetValue(const std::wstring& key, const std::wstring& value) noexcept
|
||||
{
|
||||
return RegSetValueEx(hkKeyPath, key.c_str(), 0, REG_SZ, (BYTE*)value.c_str(), value.size() * 2) == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,5 +90,48 @@ namespace pEp {
|
|||
identity_list *identities(SAFEARRAY * sa);
|
||||
::message * text_message_to_C(TextMessage *msg);
|
||||
void text_message_from_C(TextMessage *msg2, const ::message *msg);
|
||||
|
||||
/// <summary>
|
||||
/// Little utility class to read/write from the windows registry
|
||||
/// </summary>
|
||||
class RegistryKey
|
||||
{
|
||||
HKEY cu;
|
||||
bool opened = false;
|
||||
HKEY hkKeyPath = NULL;
|
||||
LONG lResult;
|
||||
std::wstring key_path;
|
||||
|
||||
LONG create_key(HKEY hk, const std::wstring& key, HKEY& hkKey) noexcept;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="keyPath">Key were the settings are to be used (e.g."Software\\pEp\\Something")</param>
|
||||
RegistryKey(const std::wstring& keyPath) noexcept;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value from a key.
|
||||
/// </summary>
|
||||
/// <param name="key">Relative (to the initialized one in constructor) key name </param>
|
||||
/// <param name="default_value">
|
||||
/// Value that will be returned in case the key
|
||||
/// does not exist or any error is produced
|
||||
/// </param>
|
||||
/// <returns>The value retrieved</returns>
|
||||
std::wstring GetValue(const std::wstring& key, const std::wstring& default_value) noexcept;
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value for a key
|
||||
/// </summary>
|
||||
/// <param name="key">Relative (to the initialized one in constructor) key name </param>
|
||||
/// <param name="value">The value to be set</param>
|
||||
bool SetValue(const std::wstring& key, const std::wstring& value) noexcept;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
#include "stdafx.h"
|
||||
#include "unpack.hh"
|
||||
|
||||
#include <system_error>
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
// FIXME: name collision possible
|
||||
static wchar_t *mkdtemp(wchar_t *_template, size_t len)
|
||||
{
|
||||
if (_wmktemp_s(_template, len+1))
|
||||
return nullptr;
|
||||
|
||||
if (_wmkdir(_template))
|
||||
return nullptr;
|
||||
|
||||
return _template;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace SignedPackage {
|
||||
static bool path_empty(std::wstring path)
|
||||
{
|
||||
if (!std::filesystem::exists(path))
|
||||
return true;
|
||||
if (!std::filesystem::is_directory(path))
|
||||
return false;
|
||||
return std::filesystem::is_empty(path);
|
||||
}
|
||||
|
||||
static void ensure_target_path(std::wstring path)
|
||||
{
|
||||
if (std::filesystem::exists(path)) {
|
||||
if (!std::filesystem::is_directory(path))
|
||||
std::filesystem::remove(path);
|
||||
}
|
||||
std::filesystem::create_directories(path);
|
||||
}
|
||||
|
||||
static std::filesystem::path mktempdir()
|
||||
{
|
||||
std::filesystem::path _path = std::filesystem::temp_directory_path() / "spXXXXXXXXXXXX";
|
||||
std::unique_ptr< wchar_t[] > buffer { ::_wcsdup(_path.c_str()) };
|
||||
if (!buffer.get())
|
||||
throw std::bad_alloc();
|
||||
|
||||
wchar_t *p = mkdtemp(buffer.get(), wcslen(buffer.get()));
|
||||
if (!p) {
|
||||
char err[512];
|
||||
if (!::strerror_s(err, sizeof(err), errno))
|
||||
throw std::filesystem::filesystem_error(err,
|
||||
std::error_code(errno, std::system_category()));
|
||||
else
|
||||
throw std::filesystem::filesystem_error("Filesystem error",
|
||||
std::error_code(errno, std::system_category()));
|
||||
}
|
||||
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
static void throw_archive_read_error(struct archive *a)
|
||||
{
|
||||
if (::archive_error_string(a)) {
|
||||
std::string error_string = ::archive_error_string(a);
|
||||
int e = ::archive_errno(a);
|
||||
::archive_read_free(a);
|
||||
throw std::filesystem::filesystem_error(error_string,
|
||||
std::error_code(e, std::system_category()));
|
||||
}
|
||||
else if (errno) {
|
||||
::archive_read_free(a);
|
||||
char err[512];
|
||||
if (!::strerror_s(err, sizeof(err), errno))
|
||||
throw std::filesystem::filesystem_error(err,
|
||||
std::error_code(errno, std::system_category()));
|
||||
else
|
||||
throw std::filesystem::filesystem_error("Filesystem error",
|
||||
std::error_code(errno, std::system_category()));
|
||||
}
|
||||
}
|
||||
|
||||
static void Load(const std::wstring& filename, CryptoPP::BufferedTransformation& bt)
|
||||
{
|
||||
CryptoPP::FileSource file(filename.c_str(), true);
|
||||
|
||||
file.TransferTo(bt);
|
||||
bt.MessageEnd();
|
||||
}
|
||||
|
||||
void LoadPrivateKey(const std::wstring& filename, CryptoPP::PrivateKey& key)
|
||||
{
|
||||
CryptoPP::ByteQueue queue;
|
||||
Load(filename, queue);
|
||||
|
||||
key.Load(queue);
|
||||
}
|
||||
|
||||
void LoadPublicKey(const std::wstring& filename, CryptoPP::PublicKey& key)
|
||||
{
|
||||
CryptoPP::ByteQueue queue;
|
||||
Load(filename, queue);
|
||||
|
||||
key.Load(queue);
|
||||
}
|
||||
|
||||
void extract_archive(
|
||||
std::wstring pkg_path,
|
||||
std::wstring target_path
|
||||
)
|
||||
{
|
||||
std::wstring cwd = std::filesystem::current_path();
|
||||
|
||||
struct archive *a = ::archive_read_new();
|
||||
|
||||
::archive_read_support_filter_all(a);
|
||||
::archive_read_support_format_all(a);
|
||||
|
||||
int r = ::archive_read_open_filename_w(a, pkg_path.c_str(), 32768);
|
||||
if (r != ARCHIVE_OK && r != ARCHIVE_WARN) {
|
||||
std::filesystem::current_path(cwd);
|
||||
throw_archive_read_error(a);
|
||||
}
|
||||
|
||||
std::filesystem::current_path(target_path);
|
||||
|
||||
struct ::archive_entry *entry;
|
||||
while (::archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
std::string pathname{::archive_entry_pathname(entry)};
|
||||
|
||||
do {
|
||||
r = archive_read_extract(a, entry,
|
||||
ARCHIVE_EXTRACT_ACL |
|
||||
ARCHIVE_EXTRACT_FFLAGS |
|
||||
ARCHIVE_EXTRACT_MAC_METADATA |
|
||||
ARCHIVE_EXTRACT_NO_OVERWRITE |
|
||||
ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS |
|
||||
ARCHIVE_EXTRACT_SECURE_NODOTDOT |
|
||||
ARCHIVE_EXTRACT_SECURE_SYMLINKS |
|
||||
ARCHIVE_EXTRACT_TIME |
|
||||
ARCHIVE_EXTRACT_XATTR
|
||||
);
|
||||
} while (r == ARCHIVE_RETRY);
|
||||
if (r != ARCHIVE_OK && r != ARCHIVE_WARN) {
|
||||
std::filesystem::current_path(cwd);
|
||||
throw_archive_read_error(a);
|
||||
}
|
||||
}
|
||||
|
||||
::archive_read_free(a);
|
||||
std::filesystem::current_path(cwd);
|
||||
}
|
||||
|
||||
std::string decrypt_distribution_key(
|
||||
std::filesystem::path key_path,
|
||||
CryptoPP::PrivateKey& provisioning_key
|
||||
)
|
||||
{
|
||||
CryptoPP::RSAES< CryptoPP::OAEP< CryptoPP::SHA256 > >::Decryptor
|
||||
decryptor(provisioning_key);
|
||||
CryptoPP::AutoSeededRandomPool rng;
|
||||
std::string distribution_key;
|
||||
|
||||
CryptoPP::FileSource keySource(key_path.c_str(), true,
|
||||
new CryptoPP::PK_DecryptorFilter(rng, decryptor,
|
||||
new CryptoPP::StringSink(distribution_key)));
|
||||
|
||||
return distribution_key;
|
||||
}
|
||||
|
||||
void verify_distribution_signature(
|
||||
std::filesystem::path archive,
|
||||
std::filesystem::path sigfile,
|
||||
CryptoPP::PublicKey& deployment_key
|
||||
)
|
||||
{
|
||||
CryptoPP::ed25519::Verifier verifier(
|
||||
dynamic_cast< CryptoPP::X509PublicKey& >(deployment_key));
|
||||
|
||||
const size_t size = 64; // ed25519 signature size
|
||||
char signature[size];
|
||||
|
||||
{
|
||||
std::ifstream _sigfile(sigfile, std::ios_base::in |
|
||||
std::ios_base::binary);
|
||||
_sigfile.read(signature, size);
|
||||
}
|
||||
|
||||
std::ifstream _archive(archive, std::ios_base::in | std::ios_base::binary);
|
||||
assert(_archive.good());
|
||||
bool valid = verifier.VerifyStream(_archive,
|
||||
(unsigned char*) signature, size);
|
||||
if (!valid)
|
||||
throw std::runtime_error("signature does not match"); // AQUI
|
||||
}
|
||||
|
||||
std::filesystem::path decrypt_distribution_archive(
|
||||
std::filesystem::path archive,
|
||||
std::filesystem::path key_path,
|
||||
CryptoPP::PrivateKey& provisioning_key
|
||||
)
|
||||
{
|
||||
std::string distribution_key = decrypt_distribution_key(key_path,
|
||||
provisioning_key);
|
||||
|
||||
std::ifstream ifs(archive, std::ios_base::binary | std::ios_base::in);
|
||||
char iv[12]; // 96 bit is GCM standard size
|
||||
ifs.read(iv, sizeof(iv));
|
||||
|
||||
CryptoPP::GCM< CryptoPP::AES >::Decryption dec;
|
||||
dec.SetKeyWithIV((const unsigned char*) distribution_key.c_str(),
|
||||
distribution_key.size(), (const unsigned char*) iv, sizeof(iv));
|
||||
|
||||
std::filesystem::path decrypted_archive = archive.c_str() + std::wstring(L"D");
|
||||
|
||||
CryptoPP::FileSource archiveSource(ifs, true,
|
||||
new CryptoPP::AuthenticatedDecryptionFilter(dec,
|
||||
new CryptoPP::FileSink(decrypted_archive.c_str())));
|
||||
|
||||
return decrypted_archive;
|
||||
}
|
||||
|
||||
std::filesystem::path extract_deployment_archive(
|
||||
CryptoPP::PublicKey& deployment_key,
|
||||
CryptoPP::PrivateKey& provisioning_key,
|
||||
std::filesystem::path pkg_path
|
||||
)
|
||||
{
|
||||
std::filesystem::path target_path = mktempdir();
|
||||
|
||||
extract_archive(pkg_path, target_path);
|
||||
|
||||
verify_distribution_signature(target_path / "DIST.A",
|
||||
target_path / "DIST.SIG", deployment_key);
|
||||
|
||||
decrypt_distribution_archive(target_path / "DIST.A",
|
||||
target_path / "DIST.KEY", provisioning_key);
|
||||
|
||||
return target_path;
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
{
|
||||
if (path_empty(target_path)) {
|
||||
std::filesystem::path tmp_path = extract_deployment_archive(deployment_key,
|
||||
provisioning_key, pkg_path);
|
||||
|
||||
std::filesystem::path decrypted_archive =
|
||||
decrypt_distribution_archive(tmp_path / "DIST.A",
|
||||
tmp_path / "DIST.KEY", provisioning_key);
|
||||
|
||||
extract_archive(decrypted_archive, tmp_path);
|
||||
|
||||
ensure_target_path(target_path);
|
||||
for (auto const& direntry : std::filesystem::directory_iterator{tmp_path / location}) {
|
||||
std::filesystem::path source = direntry.path();
|
||||
std::filesystem::rename(direntry.path(), target_path / source.filename());
|
||||
}
|
||||
|
||||
std::filesystem::remove_all(tmp_path);
|
||||
}
|
||||
}
|
||||
|
||||
//void provision_user(
|
||||
// pEp::UpdateClient::product p,
|
||||
// pEp::UpdateClient::PublicKey update_key,
|
||||
// CryptoPP::PublicKey& deployment_key,
|
||||
// CryptoPP::PrivateKey& provisioning_key,
|
||||
// pEp::notifyRead_t notifyRead,
|
||||
// locations loc
|
||||
// )
|
||||
//{
|
||||
// std::string target_path = loc["PER_USER_DIRECTORY"];
|
||||
|
||||
// // do not provision systems, which formerly were used
|
||||
// if (!path_empty(target_path))
|
||||
// return;
|
||||
|
||||
// std::string pkg_path = pEp::UpdateClient::update(p, update_key, notifyRead);
|
||||
// install_if_location_empty(deployment_key, provisioning_key, pkg_path, "PER_USER_DIRECTORY", target_path);
|
||||
// std::filesystem::remove(pkg_path);
|
||||
//}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#ifndef SP_UNPACK
|
||||
#define SP_UNPACK
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
|
||||
#include <cryptopp/files.h>
|
||||
#include <cryptopp/oaep.h>
|
||||
#include <cryptopp/osrng.h>
|
||||
#include <cryptopp/xed25519.h>
|
||||
#include <cryptopp/rsa.h>
|
||||
#include <cryptopp/gcm.h>
|
||||
#include <codecvt>
|
||||
|
||||
|
||||
#include <pEp/pEpEngine.h>
|
||||
//#include <pEp/downloadclient.hh>
|
||||
#include "utf8_helper.h"
|
||||
|
||||
namespace SignedPackage {
|
||||
// locations maps installation location name to actual POSIX path
|
||||
typedef std::map< std::string, std::wstring > locations;
|
||||
|
||||
const locations pEp_locations = {
|
||||
{ "PER_USER_DIRECTORY", pEp::utility::utf16_string(::per_user_directory()) },
|
||||
{ "PER_MACHINE_DIRECTORY", pEp::utility::utf16_string(::per_machine_directory()) }
|
||||
};
|
||||
|
||||
void LoadPrivateKey(const std::wstring& filename, CryptoPP::PrivateKey& key);
|
||||
void LoadPublicKey(const std::wstring& filename, CryptoPP::PublicKey& key);
|
||||
|
||||
void extract_archive(
|
||||
std::wstring pkg_path,
|
||||
std::wstring target_path
|
||||
);
|
||||
|
||||
void decrypt_archive(
|
||||
std::filesystem::path archive,
|
||||
std::filesystem::path key,
|
||||
CryptoPP::PrivateKey& provisioning_key
|
||||
);
|
||||
|
||||
std::string decrypt_distribution_key(
|
||||
std::filesystem::path key_path,
|
||||
CryptoPP::PrivateKey& provisioning_key
|
||||
);
|
||||
|
||||
void verify_distribution_signature(
|
||||
std::filesystem::path archive,
|
||||
std::filesystem::path sigfile,
|
||||
CryptoPP::PublicKey& deployment_key
|
||||
);
|
||||
|
||||
std::filesystem::path decrypt_distribution_archive(
|
||||
std::filesystem::path archive,
|
||||
std::filesystem::path key_path,
|
||||
CryptoPP::PrivateKey& provisioning_key
|
||||
);
|
||||
|
||||
std::filesystem::path extract_deployment_archive(
|
||||
CryptoPP::PublicKey& deployment_key,
|
||||
CryptoPP::PrivateKey& provisioning_key,
|
||||
std::filesystem::path pkg_path
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
/* how to provision for a user and use this API
|
||||
|
||||
#include <pEp/unpack.hh>
|
||||
|
||||
void provision(std::string url)
|
||||
{
|
||||
pEp::UpdateClient::product p { "provisioning data", url };
|
||||
|
||||
UpdateClient::PublicKey update_key;
|
||||
UpdateClient::load_key("update_key.der");
|
||||
|
||||
CryptoPP::ed25519PublicKey deployment_key;
|
||||
SignedPackage::LoadPublicKey("deployment_key-pub.der", deployment_key);
|
||||
|
||||
CryptoPP::RSA::PrivateKey provisioning_key;
|
||||
SignedPackage::LoadPrivateKey("provisioning_key.der", provisioning_key);
|
||||
|
||||
SignedPackage::provision_user(p, update_key, deployment_key,
|
||||
provisioning_key);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//void provision_user(
|
||||
// pEp::UpdateClient::product p,
|
||||
// pEp::UpdateClient::PublicKey update_key,
|
||||
// CryptoPP::PublicKey& deployment_key,
|
||||
// CryptoPP::PrivateKey& provisioning_key,
|
||||
// pEp::notifyRead_t notifyRead = nullptr,
|
||||
// locations loc = pEp_locations
|
||||
// );
|
||||
}
|
||||
|
||||
#endif // SP_UNPACK
|
Loading…
Reference in New Issue