Struct apple_codesign::SignedMachOInfo
source · pub struct SignedMachOInfo {
pub code_directory_blob: Vec<u8>,
pub designated_code_requirement: Option<String>,
}
Expand description
Metadata about a signed Mach-O file or bundle.
If referring to a bundle, the metadata refers to the 1st Mach-O in the bundle’s main executable.
This contains enough metadata to construct references to the file/bundle in crate::code_resources::CodeResources files.
Fields§
§code_directory_blob: Vec<u8>
Raw data constituting the code directory blob.
Is typically digested to construct a
designated_code_requirement: Option<String>
Designated code requirements string.
Typically occupies a <key>requirement</key>
in a
crate::code_resources::CodeResources file.
Implementations§
source§impl SignedMachOInfo
impl SignedMachOInfo
sourcepub fn parse_data(data: &[u8]) -> Result<Self, AppleCodesignError>
pub fn parse_data(data: &[u8]) -> Result<Self, AppleCodesignError>
Parse Mach-O data to obtain an instance.
Examples found in repository?
src/stapling.rs (line 57)
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
pub fn record_name_from_executable_bundle(
bundle: &DirectoryBundle,
) -> Result<String, AppleCodesignError> {
let main_exe = bundle
.files(false)
.map_err(AppleCodesignError::DirectoryBundle)?
.into_iter()
.find(|file| matches!(file.is_main_executable(), Ok(true)))
.ok_or(AppleCodesignError::StapleMainExecutableNotFound)?;
// Now extract the code signature so we can resolve the code directory.
info!(
"resolving bundle's record name from {}",
main_exe.absolute_path().display()
);
let macho_data = std::fs::read(main_exe.absolute_path())?;
let signed = SignedMachOInfo::parse_data(&macho_data)?;
let record_name = signed.notarization_ticket_record_name()?;
Ok(record_name)
}
More examples
src/bundle_signing.rs (line 374)
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
fn sign_and_install_macho(
&self,
file: &DirectoryBundleFile,
) -> Result<SignedMachOInfo, AppleCodesignError> {
info!("signing Mach-O file {}", file.relative_path().display());
let macho_data = std::fs::read(file.absolute_path())?;
let signer = MachOSigner::new(&macho_data)?;
let mut settings = self
.settings
.as_bundle_macho_settings(file.relative_path().to_string_lossy().as_ref());
settings.import_settings_from_macho(&macho_data)?;
// If there isn't a defined binary identifier, derive one from the file name so one is set
// and we avoid a signing error due to missing identifier.
// TODO do we need to check the nested Mach-O settings?
if settings.binary_identifier(SettingsScope::Main).is_none() {
let identifier = file
.relative_path()
.file_name()
.expect("failure to extract filename (this should never happen)")
.to_string_lossy();
let identifier = identifier
.strip_suffix(".dylib")
.unwrap_or_else(|| identifier.as_ref());
info!(
"Mach-O is missing binary identifier; setting to {} based on file name",
identifier
);
settings.set_binary_identifier(SettingsScope::Main, identifier);
}
let mut new_data = Vec::<u8>::with_capacity(macho_data.len() + 2_usize.pow(17));
signer.write_signed_binary(&settings, &mut new_data)?;
let dest_path = self.dest_dir.join(file.relative_path());
info!("writing Mach-O to {}", dest_path.display());
write_macho_file(file.absolute_path(), &dest_path, &new_data)?;
SignedMachOInfo::parse_data(&new_data)
}
src/code_resources.rs (line 1338)
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
pub fn process_nested_bundle(
&mut self,
relative_path: &str,
bundle: &DirectoryBundle,
) -> Result<(), AppleCodesignError> {
let main_exe = match bundle
.files(false)
.map_err(AppleCodesignError::DirectoryBundle)?
.into_iter()
.find(|file| matches!(file.is_main_executable(), Ok(true)))
{
Some(path) => path,
None => {
warn!(
"nested bundle at {} does not have main executable; nothing to seal",
relative_path
);
return Ok(());
}
};
let (relative_path, optional) =
match Self::evaluate_rules(&self.rules2, relative_path, None)? {
RulesEvaluation::SealRegularFile(relative_path, optional) => {
(relative_path, optional)
}
RulesEvaluation::SealNested(relative_path, optional) => (relative_path, optional),
RulesEvaluation::Exclude => {
info!(
"excluding signing nested bundle {} because of matched resources rule",
relative_path
);
return Ok(());
}
res => {
warn!(
"unexpected resource rules evaluation result for nested bundle {}: {:?}",
relative_path, res
);
return Err(AppleCodesignError::BundleUnexpectedResourceRuleResult);
}
};
let macho_data = std::fs::read(main_exe.absolute_path())?;
let macho_info = SignedMachOInfo::parse_data(&macho_data)?;
info!("sealing nested bundle at {}", relative_path);
self.resources
.seal_macho(relative_path, &macho_info, optional)?;
Ok(())
}
sourcepub fn code_directory(
&self
) -> Result<Box<CodeDirectoryBlob<'_>>, AppleCodesignError>
pub fn code_directory(
&self
) -> Result<Box<CodeDirectoryBlob<'_>>, AppleCodesignError>
Resolve the parsed code directory from stored data.
Examples found in repository?
src/bundle_signing.rs (line 247)
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
pub fn notarization_ticket_record_name(&self) -> Result<String, AppleCodesignError> {
let cd = self.code_directory()?;
let digest_type: u8 = cd.digest_type.into();
let mut digest = cd.digest_with(cd.digest_type)?;
// Digests appear to be truncated at 20 bytes / 40 characters.
digest.truncate(20);
let digest = hex::encode(digest);
// Unsure what the leading `2/` means.
Ok(format!("2/{digest_type}/{digest}"))
}
sourcepub fn notarization_ticket_record_name(
&self
) -> Result<String, AppleCodesignError>
pub fn notarization_ticket_record_name(
&self
) -> Result<String, AppleCodesignError>
Resolve the notarization ticket record name for this Mach-O file.
Examples found in repository?
src/stapling.rs (line 59)
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
pub fn record_name_from_executable_bundle(
bundle: &DirectoryBundle,
) -> Result<String, AppleCodesignError> {
let main_exe = bundle
.files(false)
.map_err(AppleCodesignError::DirectoryBundle)?
.into_iter()
.find(|file| matches!(file.is_main_executable(), Ok(true)))
.ok_or(AppleCodesignError::StapleMainExecutableNotFound)?;
// Now extract the code signature so we can resolve the code directory.
info!(
"resolving bundle's record name from {}",
main_exe.absolute_path().display()
);
let macho_data = std::fs::read(main_exe.absolute_path())?;
let signed = SignedMachOInfo::parse_data(&macho_data)?;
let record_name = signed.notarization_ticket_record_name()?;
Ok(record_name)
}
Auto Trait Implementations§
impl RefUnwindSafe for SignedMachOInfo
impl Send for SignedMachOInfo
impl Sync for SignedMachOInfo
impl Unpin for SignedMachOInfo
impl UnwindSafe for SignedMachOInfo
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
Causes
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
Causes
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
Causes
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
Causes
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
Causes
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
Causes
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
Causes
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
Causes
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
Formats each item in a sequence. Read more
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Pipes by value. This is generally the method you want to use. Read more
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
Borrows
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
Mutably borrows
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> Rwhere
Self: Borrow<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R
) -> Rwhere
Self: BorrowMut<B>,
B: 'a + ?Sized,
R: 'a,
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> Rwhere
Self: AsRef<U>,
U: 'a + ?Sized,
R: 'a,
Borrows
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> Rwhere
Self: AsMut<U>,
U: 'a + ?Sized,
R: 'a,
Mutably borrows
self
, then passes self.as_mut()
into the pipe
function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Immutable access to the
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Mutable access to the
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Immutable access to the
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Mutable access to the
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Selfwhere
Self: Deref<Target = T>,
T: ?Sized,
Immutable access to the
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Selfwhere
Self: DerefMut<Target = T> + Deref,
T: ?Sized,
Mutable access to the
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
Calls
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
Calls
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Selfwhere
Self: Borrow<B>,
B: ?Sized,
Calls
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Selfwhere
Self: BorrowMut<B>,
B: ?Sized,
Calls
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Selfwhere
Self: AsRef<R>,
R: ?Sized,
Calls
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Selfwhere
Self: AsMut<R>,
R: ?Sized,
Calls
.tap_ref_mut()
only in debug builds, and is erased in release
builds.