diff --git a/apple-codesign/src/bundle_signing.rs b/apple-codesign/src/bundle_signing.rs index 48170b1cb..a8c2233de 100644 --- a/apple-codesign/src/bundle_signing.rs +++ b/apple-codesign/src/bundle_signing.rs @@ -27,10 +27,14 @@ use { }; /// Copy a bundle's contents to a destination directory. +/// +/// This does not use the CodeResources rules for a bundle. Rather, it +/// blindly copies all files in the bundle. This means that excluded files +/// can be copied. pub fn copy_bundle(bundle: &DirectoryBundle, dest_dir: &Path) -> Result<(), AppleCodesignError> { let settings = SigningSettings::default(); - let handler = SingleBundleHandler { + let context = BundleSigningContext { dest_dir: dest_dir.to_path_buf(), settings: &settings, }; @@ -39,7 +43,7 @@ pub fn copy_bundle(bundle: &DirectoryBundle, dest_dir: &Path) -> Result<(), Appl .files(false) .map_err(AppleCodesignError::DirectoryBundle)? { - handler.install_file(file.absolute_path(), file.relative_path())?; + context.install_file(file.absolute_path(), file.relative_path())?; } Ok(()) @@ -260,42 +264,17 @@ impl SignedMachOInfo { } } -/// Used to process individual files within a bundle. -/// -/// This abstraction lets entities like [CodeResourcesBuilder] drive the -/// installation of files into a new bundle. -pub trait BundleFileHandler { - fn dest_dir(&self) -> &Path; - - /// Ensures a file (regular or symlink) is installed. - fn install_file( - &self, - source_path: &Path, - dest_rel_path: &Path, - ) -> Result<(), AppleCodesignError>; - - /// Sign a Mach-O file and ensure its new content is installed. - /// - /// Returns Mach-O metadata which will be recorded in - /// [crate::code_resources::CodeResources]. - fn sign_and_install_macho( - &self, - source_path: &Path, - dest_rel_path: &Path, - ) -> Result; +/// Holds state and helper methods to facilitate signing a bundle. +pub struct BundleSigningContext<'a, 'key> { + /// Settings for this bundle. + pub settings: &'a SigningSettings<'key>, + /// Where the bundle is getting installed to. + pub dest_dir: PathBuf, } -struct SingleBundleHandler<'a, 'key> { - settings: &'a SigningSettings<'key>, - dest_dir: PathBuf, -} - -impl<'a, 'key> BundleFileHandler for SingleBundleHandler<'a, 'key> { - fn dest_dir(&self) -> &Path { - &self.dest_dir - } - - fn install_file( +impl<'a, 'key> BundleSigningContext<'a, 'key> { + /// Install a file (regular or symlink) in the destination directory. + pub fn install_file( &self, source_path: &Path, dest_rel_path: &Path, @@ -345,7 +324,11 @@ impl<'a, 'key> BundleFileHandler for SingleBundleHandler<'a, 'key> { Ok(()) } - fn sign_and_install_macho( + /// Sign a Mach-O file and ensure its new content is installed. + /// + /// Returns Mach-O metadata which can be recorded in a CodeResources file. + + pub fn sign_and_install_macho( &self, source_path: &Path, dest_rel_path: &Path, @@ -445,7 +428,7 @@ impl SingleBundleSigner { // But we still need to preserve files (hopefully just symlinks) outside the // nested bundles under `Versions/`. Since we don't nest into child bundles // here, it should be safe to handle each encountered file. - let handler = SingleBundleHandler { + let context = BundleSigningContext { dest_dir: dest_dir.to_path_buf(), settings, }; @@ -455,7 +438,7 @@ impl SingleBundleSigner { .files(false) .map_err(AppleCodesignError::DirectoryBundle)? { - handler.install_file(file.absolute_path(), file.relative_path())?; + context.install_file(file.absolute_path(), file.relative_path())?; } return DirectoryBundle::new_from_path(dest_dir) @@ -555,12 +538,12 @@ impl SingleBundleSigner { ); } - let handler = SingleBundleHandler { + let context = BundleSigningContext { dest_dir: dest_dir_root.clone(), settings, }; - resources_builder.walk_and_seal_directory(self.bundle.root_dir(), &handler)?; + resources_builder.walk_and_seal_directory(self.bundle.root_dir(), &context)?; let info_plist_data = std::fs::read(self.bundle.info_plist_path())?; diff --git a/apple-codesign/src/code_resources.rs b/apple-codesign/src/code_resources.rs index 214a3e9fb..7fbd2883c 100644 --- a/apple-codesign/src/code_resources.rs +++ b/apple-codesign/src/code_resources.rs @@ -17,7 +17,7 @@ use { crate::{ - bundle_signing::{BundleFileHandler, SignedMachOInfo}, + bundle_signing::{BundleSigningContext, SignedMachOInfo}, embedded_signature::DigestType, error::AppleCodesignError, }, @@ -1101,10 +1101,10 @@ impl CodeResourcesBuilder { /// /// As a side-effect, files are copied/installed into the destination /// directory as part of sealing. - pub fn walk_and_seal_directory( + pub fn walk_and_seal_directory<'ctx, 'key>( &mut self, root: &Path, - file_handler: &dyn BundleFileHandler, + context: &BundleSigningContext<'ctx, 'key>, ) -> Result<(), AppleCodesignError> { let mut skipping_rel_dirs = BTreeSet::new(); @@ -1155,7 +1155,7 @@ impl CodeResourcesBuilder { rel_path, &rel_path_normalized, rule.optional, - file_handler.dest_dir(), + &context.dest_dir, )?; skipping_rel_dirs.insert(rel_path.to_path_buf()); @@ -1181,7 +1181,7 @@ impl CodeResourcesBuilder { if crate::reader::path_is_macho(path)? { info!("sealing nested Mach-O binary: {}", rel_path.display()); - let macho_info = file_handler.sign_and_install_macho(path, rel_path)?; + let macho_info = context.sign_and_install_macho(path, rel_path)?; self.resources.seal_macho( &rel_path_normalized, @@ -1199,7 +1199,7 @@ impl CodeResourcesBuilder { &rel_path_normalized, rule.omit, rule.optional, - file_handler, + context, )?; } } else if entry.file_type().is_symlink() { @@ -1216,7 +1216,7 @@ impl CodeResourcesBuilder { rel_path, &rel_path_normalized, rule.omit, - file_handler, + context, )?; } else { warn!( @@ -1294,14 +1294,14 @@ impl CodeResourcesBuilder { } /// Seal a file for version 2 rules. - fn seal_rules2_file( + fn seal_rules2_file<'ctx, 'key>( &mut self, full_path: &Path, rel_path: &Path, rel_path_normalized: &str, omit: bool, optional: bool, - handler: &dyn BundleFileHandler, + context: &BundleSigningContext<'ctx, 'key>, ) -> Result<(), AppleCodesignError> { // Only seal if the omit flag is unset. But install unconditionally // in all cases. @@ -1329,18 +1329,18 @@ impl CodeResourcesBuilder { .seal_regular_file(flavor, rel_path_normalized, data, optional)?; } - handler.install_file(full_path, rel_path)?; + context.install_file(full_path, rel_path)?; Ok(()) } - fn seal_rules2_symlink( + fn seal_rules2_symlink<'ctx, 'key>( &mut self, full_path: &Path, rel_path: &Path, rel_path_normalized: &str, omit: bool, - handler: &dyn BundleFileHandler, + context: &BundleSigningContext<'ctx, 'key>, ) -> Result<(), AppleCodesignError> { let link_target = std::fs::read_link(full_path)? .to_string_lossy() @@ -1351,7 +1351,7 @@ impl CodeResourcesBuilder { self.resources .seal_symlink(rel_path_normalized, link_target); } - handler.install_file(full_path, rel_path)?; + context.install_file(full_path, rel_path)?; Ok(()) }