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§

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
Hide additional 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(())
    }

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}"))
    }

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§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Converts self into T using Into<T>. Read more
Causes self to use its Binary implementation when Debug-formatted.
Causes self to use its Display implementation when Debug-formatted.
Causes self to use its LowerExp implementation when Debug-formatted.
Causes self to use its LowerHex implementation when Debug-formatted.
Causes self to use its Octal implementation when Debug-formatted.
Causes self to use its Pointer implementation when Debug-formatted.
Causes self to use its UpperExp implementation when Debug-formatted.
Causes self to use its UpperHex implementation when Debug-formatted.
Formats each item in a sequence. Read more

Returns the argument unchanged.

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Instruments this type with the current Span, returning an Instrumented wrapper. Read more

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Pipes by value. This is generally the method you want to use. Read more
Borrows self and passes that borrow into the pipe function. Read more
Mutably borrows self and passes that borrow into the pipe function. Read more
Borrows self, then passes self.borrow() into the pipe function. Read more
Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Borrows self, then passes self.as_ref() into the pipe function.
Mutably borrows self, then passes self.as_mut() into the pipe function.
Borrows self, then passes self.deref() into the pipe function.
Mutably borrows self, then passes self.deref_mut() into the pipe function.
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
Should always be Self
Immutable access to a value. Read more
Mutable access to a value. Read more
Immutable access to the Borrow<B> of a value. Read more
Mutable access to the BorrowMut<B> of a value. Read more
Immutable access to the AsRef<R> view of a value. Read more
Mutable access to the AsMut<R> view of a value. Read more
Immutable access to the Deref::Target of a value. Read more
Mutable access to the Deref::Target of a value. Read more
Calls .tap() only in debug builds, and is erased in release builds.
Calls .tap_mut() only in debug builds, and is erased in release builds.
Calls .tap_borrow() only in debug builds, and is erased in release builds.
Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Calls .tap_ref() only in debug builds, and is erased in release builds.
Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Calls .tap_deref() only in debug builds, and is erased in release builds.
Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Attempts to convert self into T using TryInto<T>. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more