Improve logging and small refactor

This commit is contained in:
nab138
2026-02-14 15:19:59 -05:00
parent adc81774b0
commit a62ce2863d
4 changed files with 135 additions and 93 deletions

View File

@@ -208,6 +208,7 @@ impl Application {
}) })
.collect(); .collect();
info!("Registered app IDs");
Ok(app_ids) Ok(app_ids)
} }

View File

@@ -5,4 +5,5 @@ pub mod cert_identity;
#[cfg(feature = "install")] #[cfg(feature = "install")]
pub mod install; pub mod install;
pub mod sideloader; pub mod sideloader;
pub mod sign;
pub use builder::{SideloaderBuilder, TeamSelection}; pub use builder::{SideloaderBuilder, TeamSelection};

View File

@@ -11,17 +11,15 @@ use crate::{
application::{Application, SpecialApp}, application::{Application, SpecialApp},
builder::MaxCertsBehavior, builder::MaxCertsBehavior,
cert_identity::CertificateIdentity, cert_identity::CertificateIdentity,
sign,
}, },
util::{device::IdeviceInfo, plist::PlistDataExtract, storage::SideloadingStorage}, util::{device::IdeviceInfo, storage::SideloadingStorage},
}; };
use std::path::PathBuf; use std::path::PathBuf;
use apple_codesign::{SigningSettings, UnifiedSigner};
use idevice::provider::IdeviceProvider; use idevice::provider::IdeviceProvider;
use plist::Dictionary; use rootcause::prelude::*;
use plist_macro::plist_to_xml_string;
use rootcause::{option_ext::OptionExt, prelude::*};
use tracing::info; use tracing::info;
pub struct Sideloader { pub struct Sideloader {
@@ -65,7 +63,7 @@ impl Sideloader {
team: Option<DeveloperTeam>, team: Option<DeveloperTeam>,
// this will be replaced with proper entitlement handling later // this will be replaced with proper entitlement handling later
increased_memory_limit: bool, increased_memory_limit: bool,
) -> Result<PathBuf, Report> { ) -> Result<(PathBuf, Option<SpecialApp>), Report> {
let team = match team { let team = match team {
Some(t) => t, Some(t) => t,
None => self.get_team().await?, None => self.get_team().await?,
@@ -138,6 +136,8 @@ impl Sideloader {
} }
} }
info!("App IDs configured");
app.apply_special_app_behavior(&special, &group_identifier, &cert_identity) app.apply_special_app_behavior(&special, &group_identifier, &cert_identity)
.await .await
.context("Failed to modify app bundle")?; .context("Failed to modify app bundle")?;
@@ -147,6 +147,8 @@ impl Sideloader {
.download_team_provisioning_profile(&team, &main_app_id, None) .download_team_provisioning_profile(&team, &main_app_id, None)
.await?; .await?;
info!("Acquired provisioning profile");
app.bundle.write_info()?; app.bundle.write_info()?;
for ext in app.bundle.app_extensions_mut() { for ext in app.bundle.app_extensions_mut() {
ext.write_info()?; ext.write_info()?;
@@ -161,34 +163,18 @@ impl Sideloader {
) )
.await?; .await?;
let mut settings = Self::signing_settings(&cert_identity)?; sign::sign(
let entitlements: Dictionary = Self::entitlements_from_prov( &mut app,
provisioning_profile.encoded_profile.as_ref(), &cert_identity,
&provisioning_profile,
&special, &special,
&team, &team,
)?;
settings
.set_entitlements_xml(
apple_codesign::SettingsScope::Main,
plist_to_xml_string(&entitlements),
) )
.context("Failed to set entitlements XML")?; .context("Failed to sign app")?;
let signer = UnifiedSigner::new(settings);
for bundle in app.bundle.collect_bundles_sorted() {
info!("Signing bundle {}", bundle.bundle_dir.display());
signer
.sign_path_in_place(&bundle.bundle_dir)
.context(format!(
"Failed to sign bundle: {}",
bundle.bundle_dir.display()
))?;
}
info!("App signed!"); info!("App signed!");
Ok(app.bundle.bundle_dir.clone()) Ok((app.bundle.bundle_dir.clone(), special))
} }
#[cfg(feature = "install")] #[cfg(feature = "install")]
@@ -197,7 +183,7 @@ impl Sideloader {
device_provider: &impl IdeviceProvider, device_provider: &impl IdeviceProvider,
app_path: PathBuf, app_path: PathBuf,
increased_memory_limit: bool, increased_memory_limit: bool,
) -> Result<(), Report> { ) -> Result<Option<SpecialApp>, Report> {
let device_info = IdeviceInfo::from_device(device_provider).await?; let device_info = IdeviceInfo::from_device(device_provider).await?;
let team = self.get_team().await?; let team = self.get_team().await?;
@@ -205,11 +191,11 @@ impl Sideloader {
.ensure_device_registered(&team, &device_info.name, &device_info.udid, None) .ensure_device_registered(&team, &device_info.name, &device_info.udid, None)
.await?; .await?;
let signed_app_path = self let (signed_app_path, special_app) = self
.sign_app(app_path, Some(team), increased_memory_limit) .sign_app(app_path, Some(team), increased_memory_limit)
.await?; .await?;
info!("Installing..."); info!("Transferring App...");
crate::sideload::install::install_app(device_provider, &signed_app_path, |progress| { crate::sideload::install::install_app(device_provider, &signed_app_path, |progress| {
info!("Installing: {}%", progress); info!("Installing: {}%", progress);
@@ -217,7 +203,7 @@ impl Sideloader {
.await .await
.context("Failed to install app on device")?; .context("Failed to install app on device")?;
Ok(()) Ok(special_app)
} }
/// Get the developer team according to the configured team selection behavior /// Get the developer team according to the configured team selection behavior
pub async fn get_team(&mut self) -> Result<DeveloperTeam, Report> { pub async fn get_team(&mut self) -> Result<DeveloperTeam, Report> {
@@ -246,64 +232,4 @@ impl Sideloader {
} }
}) })
} }
pub fn signing_settings<'a>(
cert: &'a CertificateIdentity,
) -> Result<SigningSettings<'a>, Report> {
let mut settings = SigningSettings::default();
cert.setup_signing_settings(&mut settings)?;
settings.set_for_notarization(false);
settings.set_shallow(true);
Ok(settings)
}
fn entitlements_from_prov(
data: &[u8],
special: &Option<SpecialApp>,
team: &DeveloperTeam,
) -> Result<Dictionary, Report> {
let start = data
.windows(6)
.position(|w| w == b"<plist")
.ok_or_report()?;
let end = data
.windows(8)
.rposition(|w| w == b"</plist>")
.ok_or_report()?
+ 8;
let plist_data = &data[start..end];
let plist = plist::Value::from_reader_xml(plist_data)?;
let mut entitlements = plist
.as_dictionary()
.ok_or_report()?
.get_dict("Entitlements")?
.clone();
if matches!(
special,
Some(SpecialApp::SideStoreLc) | Some(SpecialApp::LiveContainer)
) {
let mut keychain_access = vec![plist::Value::String(format!(
"{}.com.kdt.livecontainer.shared",
team.team_id
))];
for number in 1..128 {
keychain_access.push(plist::Value::String(format!(
"{}.com.kdt.livecontainer.shared.{}",
team.team_id, number
)));
}
entitlements.insert(
"keychain-access-groups".to_string(),
plist::Value::Array(keychain_access),
);
}
Ok(entitlements)
}
} }

View File

@@ -0,0 +1,114 @@
use apple_codesign::{SigningSettings, UnifiedSigner};
use plist::Dictionary;
use plist_macro::plist_to_xml_string;
use rootcause::{option_ext::OptionExt, prelude::*};
use tracing::info;
use crate::{
dev::{app_ids::Profile, teams::DeveloperTeam},
sideload::{
application::{Application, SpecialApp},
cert_identity::CertificateIdentity,
},
util::plist::PlistDataExtract,
};
pub fn sign(
app: &mut Application,
cert_identity: &CertificateIdentity,
provisioning_profile: &Profile,
special: &Option<SpecialApp>,
team: &DeveloperTeam,
) -> Result<(), Report> {
let mut settings = signing_settings(cert_identity)?;
let entitlements: Dictionary = entitlements_from_prov(
provisioning_profile.encoded_profile.as_ref(),
&special,
&team,
)?;
settings
.set_entitlements_xml(
apple_codesign::SettingsScope::Main,
plist_to_xml_string(&entitlements),
)
.context("Failed to set entitlements XML")?;
let signer = UnifiedSigner::new(settings);
for bundle in app.bundle.collect_bundles_sorted() {
info!(
"Signing {}",
bundle
.bundle_dir
.file_name()
.unwrap_or(bundle.bundle_dir.as_os_str())
.to_string_lossy()
);
signer
.sign_path_in_place(&bundle.bundle_dir)
.context(format!(
"Failed to sign bundle: {}",
bundle.bundle_dir.display()
))?;
}
Ok(())
}
pub fn signing_settings<'a>(cert: &'a CertificateIdentity) -> Result<SigningSettings<'a>, Report> {
let mut settings = SigningSettings::default();
cert.setup_signing_settings(&mut settings)?;
settings.set_for_notarization(false);
settings.set_shallow(true);
Ok(settings)
}
fn entitlements_from_prov(
data: &[u8],
special: &Option<SpecialApp>,
team: &DeveloperTeam,
) -> Result<Dictionary, Report> {
let start = data
.windows(6)
.position(|w| w == b"<plist")
.ok_or_report()?;
let end = data
.windows(8)
.rposition(|w| w == b"</plist>")
.ok_or_report()?
+ 8;
let plist_data = &data[start..end];
let plist = plist::Value::from_reader_xml(plist_data)?;
let mut entitlements = plist
.as_dictionary()
.ok_or_report()?
.get_dict("Entitlements")?
.clone();
if matches!(
special,
Some(SpecialApp::SideStoreLc) | Some(SpecialApp::LiveContainer)
) {
let mut keychain_access = vec![plist::Value::String(format!(
"{}.com.kdt.livecontainer.shared",
team.team_id
))];
for number in 1..128 {
keychain_access.push(plist::Value::String(format!(
"{}.com.kdt.livecontainer.shared.{}",
team.team_id, number
)));
}
entitlements.insert(
"keychain-access-groups".to_string(),
plist::Value::Array(keychain_access),
);
}
Ok(entitlements)
}