Correct TSS request implementation

This commit is contained in:
Jackson Coxson
2025-02-05 17:32:43 -07:00
parent ab1b999a5e
commit 5615059375
2 changed files with 37 additions and 53 deletions

View File

@@ -116,7 +116,7 @@ impl ImageMounter {
let res = self.idevice.read_plist().await?;
match res.get("Status") {
Some(plist::Value::String(s)) => {
if s.as_str() != "Success" {
if s.as_str() != "Complete" {
log::error!("Image send failure: {s:?}");
return Err(IdeviceError::UnexpectedResponse);
}
@@ -131,8 +131,8 @@ impl ImageMounter {
&mut self,
image_type: impl Into<String>,
signature: Vec<u8>,
trust_cache: Vec<u8>,
info_plist: plist::Value,
trust_cache: Option<Vec<u8>>,
info_plist: Option<plist::Value>,
) -> Result<(), IdeviceError> {
let image_type = image_type.into();
@@ -140,8 +140,12 @@ impl ImageMounter {
req.insert("Command".into(), "MountImage".into());
req.insert("ImageType".into(), image_type.into());
req.insert("ImageSignature".into(), plist::Value::Data(signature));
if let Some(trust_cache) = trust_cache {
req.insert("ImageTrustCache".into(), plist::Value::Data(trust_cache));
}
if let Some(info_plist) = info_plist {
req.insert("ImageInfoPlist".into(), info_plist);
}
self.idevice
.send_plist(plist::Value::Dictionary(req))
.await?;
@@ -150,7 +154,7 @@ impl ImageMounter {
match res.get("Status") {
Some(plist::Value::String(s)) => {
if s.as_str() != "Success" {
if s.as_str() != "Complete" {
log::error!("Image send failure: {s:?}");
return Err(IdeviceError::UnexpectedResponse);
}
@@ -289,13 +293,7 @@ impl ImageMounter {
) -> Result<(), IdeviceError> {
self.upload_image("Developer", image, signature.clone())
.await?;
self.mount_image(
"Developer",
signature,
Vec::new(),
plist::Value::Dictionary(plist::Dictionary::new()),
)
.await?;
self.mount_image("Developer", signature, None, None).await?;
Ok(())
}
@@ -337,22 +335,8 @@ impl ImageMounter {
self.upload_image("Personalized", &image, manifest.clone())
.await?;
let mut extras = plist::Dictionary::new();
if let Some(info) = info_plist {
extras.insert("ImageInfoPlist".into(), info);
}
extras.insert(
"ImageTrustCache".into(),
plist::Value::Data(trust_cache.clone()),
);
debug!("Mounting image");
self.mount_image(
"Personalized",
manifest,
trust_cache,
plist::Value::Dictionary(extras),
)
self.mount_image("Personalized", manifest, Some(trust_cache), info_plist)
.await?;
Ok(())
@@ -487,6 +471,7 @@ impl ImageMounter {
parameters.insert("ApSupportsImg4".into(), true.into());
for (key, manifest_item) in manifest {
println!("{key}, {manifest_item:?}");
let manifest_item = match manifest_item {
plist::Value::Dictionary(m) => m,
_ => {
@@ -494,15 +479,12 @@ impl ImageMounter {
continue;
}
};
let info = match manifest_item.get("Info") {
Some(plist::Value::Dictionary(i)) => i,
_ => {
if manifest_item.get("Info").is_none() {
debug!("Manifest item didn't contain info");
continue;
}
};
match info.get("Trusted") {
match manifest_item.get("Trusted") {
Some(plist::Value::Boolean(t)) => {
if !t {
debug!("Info item isn't trusted");
@@ -518,13 +500,16 @@ impl ImageMounter {
let mut tss_entry = manifest_item.clone();
tss_entry.remove("Info");
if let Some(plist::Value::Dictionary(l)) = manifest.get("LoadableTrustCache") {
if let Some(plist::Value::Dictionary(i)) = l.get("Info") {
if let Some(plist::Value::Array(rules)) = i.get("RestoreRequestRules") {
if let Some(info) = manifest
.get("LoadableTrustCache")
.and_then(|l| l.as_dictionary())
.and_then(|l| l.get("Info"))
.and_then(|i| i.as_dictionary())
{
if let Some(plist::Value::Array(rules)) = info.get("RestoreRequestRules") {
crate::tss::apply_restore_request_rules(&mut tss_entry, &parameters, rules);
}
}
}
if manifest_item.get("Digest").is_none() {
tss_entry.insert("Digest".into(), plist::Value::Data(vec![]));

View File

@@ -9,6 +9,7 @@ use crate::{util::plist_to_bytes, IdeviceError};
const TSS_CLIENT_VERSION_STRING: &str = "libauthinstall-1033.0.2";
const TSS_CONTROLLER_ACTION_URL: &str = "http://gs.apple.com/TSS/controller?action=2";
#[derive(Debug)]
pub struct TSSRequest {
inner: plist::Dictionary,
}
@@ -32,6 +33,7 @@ impl TSSRequest {
}
pub async fn send(&self) -> Result<plist::Value, IdeviceError> {
debug!("Sending TSS request: {:#?}", self.inner);
let client = reqwest::Client::new();
let res = client
@@ -75,15 +77,15 @@ pub fn apply_restore_request_rules(
) {
for rule in rules {
if let plist::Value::Dictionary(rule) = rule {
let mut conditions_fulfulled = true;
let conditions = match rule.get("Conditions") {
Some(plist::Value::Dictionary(c)) => c,
_ => {
warn!("Conditions doesn't exist or wasn't a dictionary!!");
warn!("Conditions doesn't exist or wasn't a dictionary!");
continue;
}
};
let mut conditions_fulfilled = true;
for (key, value) in conditions {
let value2 = match key.as_str() {
"ApRawProductionMode" => parameters.get("ApProductionMode"),
@@ -98,24 +100,20 @@ pub fn apply_restore_request_rules(
}
};
conditions_fulfulled = match value2 {
Some(value2) => value == value2,
None => false,
};
if !conditions_fulfulled {
break;
if value2.is_none() || value2 != Some(value) {
conditions_fulfilled = false;
break; // Stop checking other conditions immediately
}
}
if !conditions_fulfulled {
if !conditions_fulfilled {
continue;
}
let actions = match rule.get("Actions") {
Some(plist::Value::Dictionary(a)) => a,
_ => {
warn!("Actions doesn't exist or wasn't a dictionary!!");
warn!("Actions doesn't exist or wasn't a dictionary!");
continue;
}
};
@@ -132,6 +130,7 @@ pub fn apply_restore_request_rules(
}
}
input.remove(key); // Explicitly remove before inserting, like Python
input.insert(key.to_owned(), value.to_owned());
}
} else {