Use correct packets for mounting

This commit is contained in:
Jackson Coxson
2025-02-05 11:40:34 -07:00
parent 732940581e
commit 74e0f8e226
4 changed files with 58 additions and 11 deletions

View File

@@ -32,12 +32,14 @@ byteorder = { version = "1.5", optional = true }
reqwest = { version = "0.12", features = ["json"], optional = true }
sha2 = { version = "0.10", optional = true }
[features]
core_device_proxy = ["dep:serde_json", "dep:json", "dep:byteorder"]
heartbeat = []
installation_proxy = []
mounter = []
mounter = ["dep:sha2"]
usbmuxd = []
tcp = ["tokio/net"]
tss = ["dep:uuid", "dep:reqwest"]

View File

@@ -86,7 +86,24 @@ impl Idevice {
/// Sends raw bytes to the socket
async fn send_raw(&mut self, message: &[u8]) -> Result<(), IdeviceError> {
if let Some(socket) = &mut self.socket {
Ok(socket.write_all(message).await?)
let mut trash = [0; 2048];
let _ = socket.read(&mut trash).await.ok();
let message_parts = message.chunks(2048);
let part_len = message_parts.len();
let mut err = 5;
for (i, part) in message_parts.enumerate() {
debug!("Writing {i}/{part_len}");
while let Err(e) = socket.write_all(part).await {
err -= 1;
if err == 0 {
return Err(e.into());
}
}
err = 5;
}
Ok(())
} else {
Err(IdeviceError::NoEstablishedConnection)
}
@@ -210,6 +227,9 @@ pub enum IdeviceError {
#[error("device not found")]
DeviceNotFound,
#[error("device lockded")]
DeviceLocked,
#[error("device refused connection")]
UsbConnectionRefused,
#[error("bad command")]
@@ -236,6 +256,7 @@ impl IdeviceError {
"GetProhibited" => Some(Self::GetProhibited),
"InvalidHostID" => Some(Self::InvalidHostID),
"SessionInactive" => Some(Self::SessionInactive),
"DeviceLocked" => Some(Self::DeviceLocked),
_ => None,
}
}

View File

@@ -1,9 +1,9 @@
// Jackson Coxson
use crate::{
lockdownd::LockdowndClient, tss::TSSRequest, util::hashmap_to_dictionary, Idevice,
IdeviceError, IdeviceService,
};
use log::debug;
use openssl::sha::Sha384;
use crate::{lockdownd::LockdowndClient, tss::TSSRequest, Idevice, IdeviceError, IdeviceService};
pub struct ImageMounter {
idevice: Idevice,
@@ -81,11 +81,18 @@ impl ImageMounter {
signature: Vec<u8>,
) -> Result<(), IdeviceError> {
let image_type = image_type.into();
let image_size = match u64::try_from(image.len()) {
Ok(i) => i,
Err(e) => {
log::error!("Could not parse image size as u64: {e:?}");
return Err(IdeviceError::UnexpectedResponse);
}
};
let mut req = plist::Dictionary::new();
req.insert("Command".into(), "ReceiveBytes".into());
req.insert("ImageType".into(), image_type.into());
req.insert("ImageSize".into(), (image.len() as u64).into());
req.insert("ImageSize".into(), image_size.into());
req.insert("ImageSignature".into(), plist::Value::Data(signature));
self.idevice
.send_plist(plist::Value::Dictionary(req))
@@ -102,7 +109,9 @@ impl ImageMounter {
_ => return Err(IdeviceError::UnexpectedResponse),
}
debug!("Sending image bytes");
self.idevice.send_raw(image).await?;
debug!("Image bytes written");
let res = self.idevice.read_plist().await?;
match res.get("Status") {
@@ -278,7 +287,7 @@ impl ImageMounter {
image: &[u8],
signature: Vec<u8>,
) -> Result<(), IdeviceError> {
self.upload_image("Developer", &image, signature.clone())
self.upload_image("Developer", image, signature.clone())
.await?;
self.mount_image(
"Developer",
@@ -291,8 +300,11 @@ impl ImageMounter {
Ok(())
}
/// Calling this has the potential of closing the socket,
/// so a provider is required for this abstraction.
pub async fn mount_personalized(
&mut self,
provider: &dyn crate::provider::IdeviceProvider,
image: Vec<u8>,
trust_cache: Vec<u8>,
build_manifest: &[u8],
@@ -300,20 +312,28 @@ impl ImageMounter {
unique_chip_id: u64,
) -> Result<(), IdeviceError> {
// Try to fetch personalization manifest
let mut hasher = Sha384::new();
hasher.update(&image);
let image_hash = hasher.finish();
let manifest = match self
.query_personalization_manifest("DeveloperDiskImage", image.clone()) // TODO:
.query_personalization_manifest("DeveloperDiskImage", image_hash.to_vec())
.await
{
Ok(manifest) => manifest,
Err(IdeviceError::NotFound) => {
Err(e) => {
debug!("Device didn't contain a manifest: {e:?}, fetching from TSS");
// On failure, the socket closes. Open a new one.
self.idevice = Self::connect(provider).await?.idevice;
// Get manifest from TSS
let manifest_dict: plist::Dictionary = plist::from_bytes(build_manifest)?;
self.get_manifest_from_tss(&manifest_dict, unique_chip_id)
.await?
}
Err(e) => return Err(e),
};
debug!("Uploading imaage");
self.upload_image("Personalized", &image, manifest.clone())
.await?;
@@ -326,6 +346,7 @@ impl ImageMounter {
plist::Value::Data(trust_cache.clone()),
);
debug!("Mounting image");
self.mount_image(
"Personalized",
manifest,

View File

@@ -49,12 +49,15 @@ impl TSSRequest {
.await?;
debug!("Apple responeded with {res}");
let res = res.trim_start_matches("STATUS=0&");
let res = res.trim_start_matches("MESSAGE=");
if !res.starts_with("SUCCESS") {
warn!("TSS responded with non-success value");
return Err(IdeviceError::UnexpectedResponse);
}
let res = res.split("REQUEST_STRING=").collect::<Vec<&str>>();
if res.len() < 2 {
warn!("Response didn't contain a request string");
return Err(IdeviceError::UnexpectedResponse);
}
Ok(plist::from_bytes(res[1].as_bytes())?)