diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 59a7122..029f62b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,6 +43,12 @@ jobs: - name: Install Rust stable uses: dtolnay/rust-toolchain@stable + - name: Install Linux dependencies + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y pkg-config libdbus-1-dev + - name: Build run: cargo build -p minimal diff --git a/README.md b/README.md index 7539f84..c07ad76 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,6 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file ## Credits - The [idevice](https://github.com/jkcoxson/idevice) crate is used to communicate with the device -- A [modified version of apple-platform-rs](https://github.com/nab138/isideload-apple-platform-rs) was used for codesigning +- A [modified version of apple-platform-rs](https://github.com/nab138/isideload-apple-platform-rs) was used for codesigning, based off [plume-apple-platform-rs](https://github.com/plumeimpactor/plume-apple-platform-rs) - [Sideloader](https://github.com/Dadoum/Sideloader) was used as a reference for how some of the private API endpoints work - [Impactor](https://github.com/khcrysalis/Impactor) was used as a reference for some cryptography code diff --git a/examples/minimal/src/main.rs b/examples/minimal/src/main.rs index 6d740de..43fa902 100644 --- a/examples/minimal/src/main.rs +++ b/examples/minimal/src/main.rs @@ -132,7 +132,7 @@ async fn main() { .machine_name("isideload-minimal".to_string()) .build(); - let result = sideloader.install_app(&provider, app_path).await; + let result = sideloader.install_app(&provider, app_path, true).await; match result { Ok(_) => println!("App installed successfully"), Err(e) => panic!("Failed to install app: {:?}", e), diff --git a/isideload/src/auth/grandslam.rs b/isideload/src/auth/grandslam.rs index 006d836..3bd88fe 100644 --- a/isideload/src/auth/grandslam.rs +++ b/isideload/src/auth/grandslam.rs @@ -97,6 +97,15 @@ impl GrandSlam { Ok(builder) } + pub fn patch(&self, url: &str) -> Result { + let builder = self + .client + .patch(url) + .headers(Self::base_headers(&self.client_info, false)?); + + Ok(builder) + } + pub async fn plist_request( &self, url: &str, diff --git a/isideload/src/dev/app_ids.rs b/isideload/src/dev/app_ids.rs index 58e6454..2187b1e 100644 --- a/isideload/src/dev/app_ids.rs +++ b/isideload/src/dev/app_ids.rs @@ -8,6 +8,7 @@ use crate::{ }; use plist::{Data, Date, Dictionary, Value}; use plist_macro::plist; +use reqwest::header::HeaderValue; use rootcause::prelude::*; use serde::Deserialize; @@ -171,6 +172,41 @@ pub trait AppIdsApi { Ok(response) } + + async fn add_increased_memory_limit( + &mut self, + team: &DeveloperTeam, + app_id: &AppId, + ) -> Result<(), Report> { + let dev_session = self.developer_session(); + + let mut headers = dev_session.get_headers().await?; + headers.insert( + "Content-Type", + HeaderValue::from_static("application/vnd.api+json"), + ); + headers.insert( + "Accept", + HeaderValue::from_static("application/vnd.api+json"), + ); + + dev_session + .get_grandslam_client() + .patch(&format!( + "https://developerservices2.apple.com/services/v1/bundleIds/{}", + app_id.app_id_id + ))? + .headers(headers) + .body(format!( + "{{\"data\":{{\"relationships\":{{\"bundleIdCapabilities\":{{\"data\":[{{\"relationships\":{{\"capability\":{{\"data\":{{\"id\":\"INCREASED_MEMORY_LIMIT\",\"type\":\"capabilities\"}}}}}},\"type\":\"bundleIdCapabilities\",\"attributes\":{{\"settings\":[],\"enabled\":true}}}}]}}}},\"id\":\"{}\",\"attributes\":{{\"hasExclusiveManagedCapabilities\":false,\"teamId\":\"{}\",\"bundleType\":\"bundle\",\"identifier\":\"{}\",\"seedId\":\"{}\",\"name\":\"{}\"}},\"type\":\"bundleIds\"}}}}", + app_id.app_id_id, team.team_id, app_id.identifier, team.team_id, app_id.name + )) + .send() + .await.context("Failed to request increased memory entitlement")? + .error_for_status().context("Failed to add increased memory entitlement")?; + + Ok(()) + } } impl AppIdsApi for DeveloperSession { diff --git a/isideload/src/dev/developer_session.rs b/isideload/src/dev/developer_session.rs index a5ee76d..f8f61d0 100644 --- a/isideload/src/dev/developer_session.rs +++ b/isideload/src/dev/developer_session.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use plist::Dictionary; use plist_macro::{plist, plist_to_xml_string}; +use reqwest::header::{HeaderMap, HeaderValue}; use rootcause::prelude::*; use serde::de::DeserializeOwned; use tracing::{error, warn}; @@ -65,6 +66,26 @@ impl DeveloperSession { )) } + pub async fn get_headers(&mut self) -> Result { + let mut headers = self + .anisette_generator + .get_anisette_data(self.client.clone()) + .await? + .get_header_map(); + + headers.insert( + "X-Apple-GS-Token", + HeaderValue::from_str(&self.token.token)?, + ); + headers.insert("X-Apple-I-Identity-Id", HeaderValue::from_str(&self.adsid)?); + + Ok(headers) + } + + pub fn get_grandslam_client(&self) -> Arc { + self.client.clone() + } + async fn send_dev_request_internal( &mut self, url: &str, @@ -85,14 +106,7 @@ impl DeveloperSession { .client .post(url)? .body(plist_to_xml_string(&body)) - .header("X-Apple-GS-Token", &self.token.token) - .header("X-Apple-I-Identity-Id", &self.adsid) - .headers( - self.anisette_generator - .get_anisette_data(self.client.clone()) - .await? - .get_header_map(), - ) + .headers(self.get_headers().await?) .send() .await? .error_for_status() diff --git a/isideload/src/sideload/sideloader.rs b/isideload/src/sideload/sideloader.rs index 377ecf8..7efcf14 100644 --- a/isideload/src/sideload/sideloader.rs +++ b/isideload/src/sideload/sideloader.rs @@ -63,6 +63,8 @@ impl Sideloader { &mut self, app_path: PathBuf, team: Option, + // this will be replaced with proper entitlement handling later + increased_memory_limit: bool, ) -> Result { let team = match team { Some(t) => t, @@ -128,7 +130,11 @@ impl Sideloader { .assign_app_group(&team, &app_group, app_id, None) .await?; - // TODO: Increased memory entitlement + if increased_memory_limit { + self.dev_session + .add_increased_memory_limit(&team, app_id) + .await?; + } } app.apply_special_app_behavior(&special, &group_identifier, &cert_identity) @@ -189,6 +195,7 @@ impl Sideloader { &mut self, device_provider: &impl IdeviceProvider, app_path: PathBuf, + increased_memory_limit: bool, ) -> Result<(), Report> { let device_info = IdeviceInfo::from_device(device_provider).await?; @@ -197,7 +204,9 @@ impl Sideloader { .ensure_device_registered(&team, &device_info.name, &device_info.udid, None) .await?; - let signed_app_path = self.sign_app(app_path, Some(team)).await?; + let signed_app_path = self + .sign_app(app_path, Some(team), increased_memory_limit) + .await?; info!("Installing...");