diff --git a/.gitignore b/.gitignore index 9840e28..2a1e305 100644 --- a/.gitignore +++ b/.gitignore @@ -191,3 +191,4 @@ test/DIST.* test/_DIST.* test/PER_* test/*.ppk +test/pEp.target diff --git a/src/unpack.cc b/src/unpack.cc index 3b0f8d1..91f520f 100644 --- a/src/unpack.cc +++ b/src/unpack.cc @@ -85,8 +85,7 @@ namespace SignedPackage { void extract_archive( std::string pkg_path, - std::string target_path, - std::vector< std::string > filenames + std::string target_path ) { std::string cwd = std::filesystem::current_path(); @@ -105,42 +104,27 @@ namespace SignedPackage { std::filesystem::current_path(target_path); struct ::archive_entry *entry; - int n = 0; while (::archive_read_next_header(a, &entry) == ARCHIVE_OK) { std::string pathname{::archive_entry_pathname(entry)}; - if (!filenames.size() || std::find(filenames.begin(), - filenames.end(), pathname) != filenames.end()) { - 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); - } - ++n; + 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); } } - if (filenames.size() && n < filenames.size()) { - ::archive_read_free(a); - std::filesystem::current_path(cwd); - throw std::range_error("illegal archive: missing file"); - } - else if (filenames.size() && n > filenames.size()) { - ::archive_read_free(a); - std::filesystem::current_path(cwd); - throw std::range_error("corrupt archive: double file"); - } ::archive_read_free(a); std::filesystem::current_path(cwd); @@ -197,7 +181,7 @@ namespace SignedPackage { { std::filesystem::path target_path = mktempdir(); - extract_archive(pkg_path, target_path, { "DIST.A", "DIST.KEY" }); + extract_archive(pkg_path, target_path); decrypt_distribution_archive(target_path / "DIST.A", target_path / "DIST.KEY", provisioning_key); @@ -208,6 +192,7 @@ namespace SignedPackage { CryptoPP::PublicKey& deployment_key, CryptoPP::PrivateKey& provisioning_key, std::filesystem::path pkg_path, + std::string location, std::filesystem::path target_path ) { @@ -218,10 +203,14 @@ namespace SignedPackage { std::filesystem::path decrypted_archive = decrypt_distribution_archive(tmp_path / "DIST.A", tmp_path / "DIST.KEY", provisioning_key); - std::filesystem::remove(tmp_path / "DIST.A"); + + extract_archive(decrypted_archive, tmp_path); ensure_target_path(target_path); - extract_archive(decrypted_archive, 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); } @@ -243,7 +232,7 @@ namespace SignedPackage { return; std::string pkg_path = pEp::UpdateClient::update(p, update_key, notifyRead); - install_if_location_empty(deployment_key, provisioning_key, pkg_path, target_path); + install_if_location_empty(deployment_key, provisioning_key, pkg_path, "PER_USER_DIRECTORY", target_path); std::filesystem::remove(pkg_path); } } diff --git a/src/unpack.hh b/src/unpack.hh index 54a905c..a4fbd22 100644 --- a/src/unpack.hh +++ b/src/unpack.hh @@ -19,8 +19,7 @@ namespace SignedPackage { void extract_archive( std::string pkg_path, - std::string target_path, - std::vector< std::string > filenames = { } + std::string target_path ); void decrypt_archive( @@ -50,6 +49,7 @@ namespace SignedPackage { CryptoPP::PublicKey& deployment_key, CryptoPP::PrivateKey& provisioning_key, std::filesystem::path pkg_path, + std::string location, std::filesystem::path target_path ); diff --git a/test/test_unpack.cc b/test/test_unpack.cc index 2486531..64f62ba 100644 --- a/test/test_unpack.cc +++ b/test/test_unpack.cc @@ -33,7 +33,7 @@ void test_extract_archive() SignedPackage::extract_archive("DIST.AD", "."); std::cout << "works: DIST.AD extracted\n"; - SignedPackage::extract_archive("DIST.AD", ".", { "PER_USER_DIRECTORY/testfile.testdata" }); + SignedPackage::extract_archive("DIST.AD", "."); std::cout << "works: file archive_file1.testdata extracted\n"; try { @@ -70,7 +70,8 @@ void test_decrypt_distribution_archive() CryptoPP::RSA::PrivateKey provisioning_key; LoadPrivateKey("provisioning_key.der", provisioning_key); - SignedPackage::decrypt_distribution_archive("DIST.A", "DIST.KEY", provisioning_key); + SignedPackage::decrypt_distribution_archive("DIST.A", "DIST.KEY", + provisioning_key); } void test_extract_deployment_archive() @@ -83,12 +84,11 @@ void test_extract_deployment_archive() CryptoPP::RSA::PrivateKey provisioning_key; LoadPrivateKey("provisioning_key.der", provisioning_key); - std::filesystem::path tmp_path = SignedPackage::extract_deployment_archive(deployment_key, provisioning_key, "pEp.ppk"); + std::filesystem::path tmp_path = + SignedPackage::extract_deployment_archive(deployment_key, + provisioning_key, "pEp.ppk"); std::cout << "extraced to " << tmp_path << "\n"; - // test if DIST.AD exists - std::filesystem::remove(tmp_path / "DIST.AD"); - std::filesystem::remove_all(tmp_path); } @@ -102,7 +102,8 @@ void test_install_if_location_empty() CryptoPP::RSA::PrivateKey provisioning_key; LoadPrivateKey("provisioning_key.der", provisioning_key); - SignedPackage::install_if_location_empty(deployment_key, provisioning_key, "pEp.ppk", "pEp.target"); + SignedPackage::install_if_location_empty(deployment_key, provisioning_key, + "pEp.ppk", "PER_USER_DIRECTORY", "pEp.target"); } int main()