Skip to content

Commit

Permalink
apple-codesign: refactor bundle file handler
Browse files Browse the repository at this point in the history
We don't need a trait here. A single struct will do fine.

This also paves the road to accessing Settings from the context of
bundle signing. This will enable retrieving settings from nested
entities.
  • Loading branch information
indygreg committed Nov 6, 2023
1 parent 30f125a commit f58bb57
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 54 deletions.
65 changes: 24 additions & 41 deletions apple-codesign/src/bundle_signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -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(())
Expand Down Expand Up @@ -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<SignedMachOInfo, AppleCodesignError>;
/// 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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
Expand All @@ -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)
Expand Down Expand Up @@ -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())?;

Expand Down
26 changes: 13 additions & 13 deletions apple-codesign/src/code_resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use {
crate::{
bundle_signing::{BundleFileHandler, SignedMachOInfo},
bundle_signing::{BundleSigningContext, SignedMachOInfo},
embedded_signature::DigestType,
error::AppleCodesignError,
},
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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());
Expand All @@ -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,
Expand All @@ -1199,7 +1199,7 @@ impl CodeResourcesBuilder {
&rel_path_normalized,
rule.omit,
rule.optional,
file_handler,
context,
)?;
}
} else if entry.file_type().is_symlink() {
Expand All @@ -1216,7 +1216,7 @@ impl CodeResourcesBuilder {
rel_path,
&rel_path_normalized,
rule.omit,
file_handler,
context,
)?;
} else {
warn!(
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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()
Expand All @@ -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(())
}
Expand Down

0 comments on commit f58bb57

Please sign in to comment.