Git · dadoum.zone
Repositories
Help
Report an Issue
apple-crates
Code
Commits
Branches
Tags
Search
Tree:
a74924e
Branches
Tags
main
apple-crates
apple-codesign-quick
src
provisioning.rs
Refactor and unify a lot of things for another project and implement airdrop support
Dadoum
commited
a74924e
at 2026-10-25 22:15:58
provisioning.rs
Blame
History
Raw
use crate::error::{CodeSignError, Result}; use cms::cert::CertificateChoices; use cms::content_info::ContentInfo; use cms::signed_data::SignedData; use der::{Decode, Encode}; use plist::{Dictionary, Value}; #[derive(Clone, Debug)] pub struct ProvisioningProfile { plist: Dictionary, team_id: String, entitlements: Dictionary, certificate_chain: Vec<Vec<u8>>, } impl ProvisioningProfile { /// Parse an embedded.mobileprovision: a CMS SignedData around an XML property list. pub fn parse(data: &[u8]) -> Result<Self> { let content_info = ContentInfo::from_der(data).map_err(CodeSignError::provisioning_profile)?; if content_info.content_type != const_oid::db::rfc5911::ID_SIGNED_DATA { return Err(CodeSignError::provisioning_profile( "the CMS content is not SignedData", )); } let signed_data: SignedData = content_info .content .decode_as() .map_err(CodeSignError::provisioning_profile)?; let profile_data = signed_data .encap_content_info .econtent .as_ref() .ok_or_else(|| CodeSignError::provisioning_profile("there is no embedded plist"))?; let plist: Dictionary = plist::from_bytes(profile_data.value())?; // Old profiles may lack TeamIdentifier, their App ID prefix was the team then. let team_id = ["TeamIdentifier", "ApplicationIdentifierPrefix"] .into_iter() .find_map(|key| { plist .get(key) .and_then(Value::as_array) .and_then(|values| values.first()) .and_then(Value::as_string) }) .ok_or_else(|| CodeSignError::provisioning_profile("there is no TeamIdentifier"))? .to_string(); let entitlements = plist .get("Entitlements") .and_then(Value::as_dictionary) .cloned() .ok_or_else(|| { CodeSignError::provisioning_profile("there is no Entitlements dictionary") })?; // These are the certificates that signed the profile, not DeveloperCertificates. let certificate_chain: der::Result<Vec<_>> = signed_data .certificates .iter() .flat_map(|certificates| certificates.0.iter()) .filter_map(|certificate| match certificate { CertificateChoices::Certificate(certificate) => Some(certificate.to_der()), _ => None, }) .collect(); let certificate_chain = certificate_chain.map_err(CodeSignError::provisioning_profile)?; Ok(ProvisioningProfile { plist, team_id, entitlements, certificate_chain, }) } pub fn plist(&self) -> &Dictionary { &self.plist } pub fn team_id(&self) -> &str { &self.team_id } pub fn entitlements(&self) -> &Dictionary { &self.entitlements } pub fn certificate_chain_der(&self) -> &[Vec<u8>] { &self.certificate_chain } }