From 8b7e594d338dfe9a175d1e6f877bf6b22056178f Mon Sep 17 00:00:00 2001 From: Chris Punches Date: Sun, 23 Mar 2025 19:51:18 -0400 Subject: [PATCH] adding missing files from previous, and various fixes for PGP signing; path mgmt is a little clunky --- modules/build/include/sealing.hpp | 4 +- modules/build/include/signing.hpp | 1 + modules/build/src/sealing.cpp | 74 +++++++++++++++++-------------- modules/build/src/signing.cpp | 65 ++++++++++++++++++++++++--- 4 files changed, 104 insertions(+), 40 deletions(-) diff --git a/modules/build/include/sealing.hpp b/modules/build/include/sealing.hpp index c47a806..8be6805 100644 --- a/modules/build/include/sealing.hpp +++ b/modules/build/include/sealing.hpp @@ -57,12 +57,12 @@ int seal_final_package(const std::string &stage_dir, const std::string &output_d * Extracts a sealed package file back to its original stage directory structure * by expanding the gzipped tarballs. * - * @param package_path Path to the sealed package file + * @param package_filepath Path to the sealed package file * @param output_dir Path to extract the package stage to * @param force Whether to force the operation even if warnings occur * @return 0 on success, non-zero on failure */ -int unseal_package(const std::string& package_path, const std::string& output_dir, bool force); +int unseal_package(const std::string& package_filepath, const std::string& output_dir, bool force); /** diff --git a/modules/build/include/signing.hpp b/modules/build/include/signing.hpp index 7430d2a..ac6f93c 100644 --- a/modules/build/include/signing.hpp +++ b/modules/build/include/signing.hpp @@ -18,6 +18,7 @@ #include #include #include "helpers.hpp" +#include "sealing.hpp" /** * @brief Signs a package stage directory diff --git a/modules/build/src/sealing.cpp b/modules/build/src/sealing.cpp index 84eac88..9619166 100644 --- a/modules/build/src/sealing.cpp +++ b/modules/build/src/sealing.cpp @@ -500,11 +500,13 @@ int seal_final_package(const std::string &stage_dir, const std::string &output_d // the user supplied an output directory so call it stage_name.dpm and prefix the path // with the output dir std::string stage_basename = stage_path.filename().string(); - output_path = output_dir + stage_basename + ".dpm"; + + // it's here + output_path = std::filesystem::path(output_dir) / std::filesystem::path(stage_basename + ".dpm"); } dpm_log( LOG_INFO, "Sealing DPM Package." ); - bool result = compress_directory( stage_path, output_path.string() ); + bool result = compress_directory( stage_path.string(), output_path.string() ); if ( ! result ) { dpm_log( LOG_FATAL, "Could not create DPM package from stage." ); return 1; @@ -513,46 +515,52 @@ int seal_final_package(const std::string &stage_dir, const std::string &output_d return 0; } -int unseal_package(const std::string& package_path, const std::string& output_dir_arg, bool force) +int unseal_package(const std::string& package_filepath, const std::string& output_dir, bool force) { - dpm_log(LOG_INFO, ("Unsealing package: " + package_path).c_str()); + dpm_log(LOG_INFO, ("Unsealing package: " + package_filepath).c_str()); - // Determine the output directory path - std::filesystem::path output_path; + // Extract filename from package path + std::filesystem::path supplied_package_path(package_filepath); + std::string package_filename = supplied_package_path.filename().string(); - if (output_dir_arg.empty()) { - // Extract filename from package path - std::filesystem::path package_fs_path(package_path); - std::string package_name = package_fs_path.filename().string(); - - // Verify it has .dpm extension - const std::string dpm_extension = ".dpm"; - if (!package_name.ends_with(dpm_extension)) { - dpm_log(LOG_FATAL, "Refusing to unseal package: file must have .dpm extension"); - return 1; - } - - // Remove .dpm extension - std::string stage_name = package_name.substr(0, package_name.length() - dpm_extension.length()); - - // Set output path to parent_directory/filename_without_extension - output_path = package_fs_path.parent_path() / stage_name; - } else { - // Use the provided output directory - output_path = std::filesystem::path(output_dir_arg); + // Verify it has .dpm extension + const std::string dpm_extension = ".dpm"; + if (!package_filename.ends_with(dpm_extension)) { + dpm_log(LOG_FATAL, "Refusing to unseal package: file must have .dpm extension"); + return 1; } - // Check if output directory already exists - if (std::filesystem::exists(output_path)) { + // Remove .dpm extension to establish the tatget stage directory to extract to + std::string target_stage_name = package_filename.substr(0, package_filename.length() - dpm_extension.length()); + + // Determine the output directory path based on whether output_dir was supplied or not + std::filesystem::path output_directory; + + if (output_dir.empty()) { + // output_dir was not supplied, so set it to the supplied package path's parent dir + target_stage_name + + // Set output path to parent_directory/filename_without_extension + output_directory = supplied_package_path.parent_path() / target_stage_name; + } else { + // output_dir was supplied, so use that + + // Use the provided output directory + output_directory = std::filesystem::path(output_dir) / target_stage_name; + } + + // Check if target path already exists + if (std::filesystem::exists(output_directory)) { if (!force) { - dpm_log(LOG_ERROR, ("Output directory already exists: " + output_path.string() + + // a stage dir already exists with this name at that path so it can't be used unless --force is used + // to overwrite it + dpm_log(LOG_ERROR, ("Output directory already exists: " + output_directory.string() + ". Use --force to overwrite.").c_str()); return 1; } // If force flag is set, remove the existing directory try { - std::filesystem::remove_all(output_path); + std::filesystem::remove_all(output_directory); } catch (const std::filesystem::filesystem_error& e) { dpm_log(LOG_ERROR, ("Failed to remove existing directory: " + std::string(e.what())).c_str()); return 1; @@ -561,20 +569,20 @@ int unseal_package(const std::string& package_path, const std::string& output_di // Create the output directory try { - std::filesystem::create_directories(output_path); + std::filesystem::create_directories(output_directory); } catch (const std::filesystem::filesystem_error& e) { dpm_log(LOG_ERROR, ("Failed to create output directory: " + std::string(e.what())).c_str()); return 1; } // Extract the package to the output directory - bool result = uncompress_archive(package_path, output_path.string()); + bool result = uncompress_archive(package_filepath, output_directory.string()); if (!result) { dpm_log(LOG_ERROR, "Failed to extract package"); return 1; } - dpm_log(LOG_INFO, ("Package unsealed successfully to: " + output_path.string()).c_str()); + dpm_log(LOG_INFO, ("Package unsealed successfully to: " + output_directory.string()).c_str()); return 0; } diff --git a/modules/build/src/signing.cpp b/modules/build/src/signing.cpp index 4e5528d..e2df933 100644 --- a/modules/build/src/signing.cpp +++ b/modules/build/src/signing.cpp @@ -1,5 +1,3 @@ -// File: signing.cpp - #include "signing.hpp" /** @@ -194,8 +192,65 @@ int sign_stage_directory(const std::string& stage_dir, const std::string& key_id } int sign_package_file(const std::string& package_path, const std::string& key_id, bool force) { - // This is a placeholder implementation dpm_log(LOG_INFO, ("Signing package file: " + package_path).c_str()); - dpm_log(LOG_ERROR, "Package file signing not yet implemented"); - return 1; + + // Get the temporary stage path by removing .dpm extension + std::string tmp_stage_path = package_path; + if (tmp_stage_path.ends_with(".dpm")) { + tmp_stage_path = tmp_stage_path.substr(0, tmp_stage_path.length() - 4); + } + + // Check if temporary stage path already exists - fail if it does + if (std::filesystem::exists(tmp_stage_path)) { + dpm_log(LOG_ERROR, ("Temporary stage directory already exists: " + tmp_stage_path).c_str()); + return 1; + } + + // 1. Unseal the package to the stage parent path + std::filesystem::path stage_parent_path = std::filesystem::path(tmp_stage_path).parent_path(); + dpm_log(LOG_INFO, "Unsealing package file..."); + int result = unseal_package(package_path, stage_parent_path, force); + if (result != 0) { + dpm_log(LOG_ERROR, "Failed to unseal package file"); + return result; + } + + // 2. Sign the stage directory components + dpm_log(LOG_INFO, "Signing package components..."); + result = sign_stage_directory(tmp_stage_path, key_id, force); + if (result != 0) { + dpm_log(LOG_ERROR, "Failed to sign package components"); + return result; + } + + std::string backup_path = package_path + ".old"; + + // Back up the original package + try { + std::filesystem::rename(package_path, backup_path); + } catch (const std::filesystem::filesystem_error& e) { + dpm_log(LOG_ERROR, ("Failed to backup original package: " + std::string(e.what())).c_str()); + return 1; + } + + // 3. Create a new sealed package at the original location + dpm_log(LOG_INFO, "Creating signed package file..."); + + // seal the package path + result = seal_final_package(tmp_stage_path, stage_parent_path.string(), force); + if (result != 0) { + dpm_log(LOG_ERROR, "Failed to create signed package"); + return result; + } + + // 4. Clean up + try { + std::filesystem::remove_all(tmp_stage_path); + std::filesystem::remove(backup_path); + } catch (const std::filesystem::filesystem_error& e) { + dpm_log(LOG_WARN, ("Failed to clean up temporary files: " + std::string(e.what())).c_str()); + } + + dpm_log(LOG_INFO, ("Successfully signed package: " + package_path).c_str()); + return 0; } \ No newline at end of file