From e94d7b64489583c287a4f46660fb00bec8b35b5d Mon Sep 17 00:00:00 2001 From: nab138 Date: Wed, 6 Aug 2025 22:13:57 -0400 Subject: [PATCH] Improve error handling and fix compilation errors --- Cargo.lock | 41 +++++++++++ Cargo.toml | 9 ++- apple-private-apis/icloud-auth/Cargo.toml | 6 +- src/certificate.rs | 83 ++++++++++++----------- src/device.rs | 17 ----- src/sideload.rs | 5 +- 6 files changed, 98 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5928ded..b498827 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -677,6 +677,21 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -684,6 +699,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -692,6 +708,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.31" @@ -727,6 +754,7 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1061,6 +1089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b9d40e2753062fba4cac48cb459987dd9f66f6b777d90c546548f053bdd03c0" dependencies = [ "base64 0.22.1", + "chrono", "env_logger", "log", "plist", @@ -1139,9 +1168,11 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" name = "isideload" version = "0.1.0" dependencies = [ + "futures", "hex", "icloud_auth", "idevice", + "openssl", "plist", "serde", "sha1", @@ -1531,6 +1562,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-src" +version = "300.5.1+3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "735230c832b28c000e3bc117119e6466a663ec73506bc0a9907ea4187508e42a" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.109" @@ -1539,6 +1579,7 @@ checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] diff --git a/Cargo.toml b/Cargo.toml index 109dbe7..f846b3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,11 @@ name = "isideload" version = "0.1.0" edition = "2024" +[features] +default = [] +vendored-openssl = ["openssl/vendored"] +vendored-botan = ["icloud_auth/vendored-botan"] + [dependencies] serde = { version = "1.0.219", features = ["derive"] } plist = { version = "1.7.2" } @@ -11,4 +16,6 @@ uuid = "1.17.0" zip = "4.3.0" hex = "0.4.3" sha1 = "0.10.6" -idevice = "0.1.37" +idevice = { version = "0.1.37", features = ["afc", "usbmuxd", "installation_proxy"] } +openssl = "0.10.73" +futures = "0.3.31" diff --git a/apple-private-apis/icloud-auth/Cargo.toml b/apple-private-apis/icloud-auth/Cargo.toml index 60d783b..d5210b5 100644 --- a/apple-private-apis/icloud-auth/Cargo.toml +++ b/apple-private-apis/icloud-auth/Cargo.toml @@ -3,7 +3,9 @@ name = "icloud_auth" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = [] +vendored-botan = ["botan/vendored"] [dependencies] serde = { version = "1.0.219", features = ["derive"] } @@ -25,7 +27,7 @@ reqwest = { version = "0.11.14", features = ["blocking", "json", "default-tls"] omnisette = {path = "../omnisette", features = ["remote-anisette-v3"]} thiserror = "1.0.58" tokio = "1" -botan = { version = "0.11.1", features = ["vendored"] } +botan = { version = "0.11.1" } chrono = { version = "0.4", features = ["serde"] } [dev-dependencies] diff --git a/src/certificate.rs b/src/certificate.rs index 2a906fa..4d23955 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -32,30 +32,29 @@ impl CertificateIdentity { let hash_string = hex::encode(hasher.finalize()).to_lowercase(); let key_path = configuration_path.join("keys").join(hash_string); fs::create_dir_all(&key_path) - .map_err(|e| format!("Failed to create key directory: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to create key directory: {}", e)))?; let key_file = key_path.join("key.pem"); let cert_file = key_path.join("cert.pem"); - let teams = dev_session - .list_teams() - .await - .map_err(|e| format!("Failed to list teams: {:?}", e))?; - let team = teams.first().ok_or("No teams found")?; + let teams = dev_session.list_teams().await?; + let team = teams + .first() + .ok_or(Error::Certificate("No teams found".to_string()))?; let private_key = if key_file.exists() { let key_data = fs::read_to_string(&key_file) - .map_err(|e| format!("Failed to read key file: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to read key file: {}", e)))?; PKey::private_key_from_pem(key_data.as_bytes()) - .map_err(|e| format!("Failed to load private key: {}", e))? + .map_err(|e| Error::Certificate(format!("Failed to load private key: {}", e)))? } else { - let rsa = - Rsa::generate(2048).map_err(|e| format!("Failed to generate RSA key: {}", e))?; - let key = - PKey::from_rsa(rsa).map_err(|e| format!("Failed to create private key: {}", e))?; + let rsa = Rsa::generate(2048) + .map_err(|e| Error::Certificate(format!("Failed to generate RSA key: {}", e)))?; + let key = PKey::from_rsa(rsa) + .map_err(|e| Error::Certificate(format!("Failed to create private key: {}", e)))?; let pem_data = key .private_key_to_pem_pkcs8() - .map_err(|e| format!("Failed to encode private key: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to encode private key: {}", e)))?; fs::write(&key_file, pem_data) - .map_err(|e| format!("Failed to save key file: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to save key file: {}", e)))?; key }; @@ -72,11 +71,12 @@ impl CertificateIdentity { { cert_identity.certificate = Some(cert.clone()); - let cert_pem = cert - .to_pem() - .map_err(|e| format!("Failed to encode certificate to PEM: {}", e))?; - fs::write(&cert_identity.cert_file, cert_pem) - .map_err(|e| format!("Failed to save certificate file: {}", e))?; + let cert_pem = cert.to_pem().map_err(|e| { + Error::Certificate(format!("Failed to encode certificate to PEM: {}", e)) + })?; + fs::write(&cert_identity.cert_file, cert_pem).map_err(|e| { + Error::Certificate(format!("Failed to save certificate file: {}", e)) + })?; return Ok(cert_identity); } @@ -116,7 +116,9 @@ impl CertificateIdentity { } } } - Error::Certificate("No matching certificate found".to_string()) + Err(Error::Certificate( + "No matching certificate found".to_string(), + )) } async fn request_new_certificate( @@ -125,40 +127,40 @@ impl CertificateIdentity { team: &DeveloperTeam, ) -> Result<(), Error> { let mut req_builder = X509ReqBuilder::new() - .map_err(|e| format!("Failed to create request builder: {}", e))?; - let mut name_builder = - X509Name::builder().map_err(|e| format!("Failed to create name builder: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to create request builder: {}", e)))?; + let mut name_builder = X509Name::builder() + .map_err(|e| Error::Certificate(format!("Failed to create name builder: {}", e)))?; name_builder .append_entry_by_text("C", "US") - .map_err(|e| format!("Failed to set country: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to set country: {}", e)))?; name_builder .append_entry_by_text("ST", "STATE") - .map_err(|e| format!("Failed to set state: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to set state: {}", e)))?; name_builder .append_entry_by_text("L", "LOCAL") - .map_err(|e| format!("Failed to set locality: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to set locality: {}", e)))?; name_builder .append_entry_by_text("O", "ORGNIZATION") - .map_err(|e| format!("Failed to set organization: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to set organization: {}", e)))?; name_builder .append_entry_by_text("CN", "CN") - .map_err(|e| format!("Failed to set common name: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to set common name: {}", e)))?; req_builder .set_subject_name(&name_builder.build()) - .map_err(|e| format!("Failed to set subject name: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to set subject name: {}", e)))?; req_builder .set_pubkey(&self.private_key) - .map_err(|e| format!("Failed to set public key: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to set public key: {}", e)))?; req_builder .sign(&self.private_key, MessageDigest::sha256()) - .map_err(|e| format!("Failed to sign request: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to sign request: {}", e)))?; let csr_pem = req_builder .build() .to_pem() - .map_err(|e| format!("Failed to encode CSR: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to encode CSR: {}", e)))?; let certificate_id = dev_session .submit_development_csr( @@ -181,23 +183,24 @@ impl CertificateIdentity { let certificates = dev_session .list_all_development_certs(DeveloperDeviceType::Ios, team) - .await - .map_err(|e| format!("Failed to list certificates: {:?}", e))?; + .await?; let apple_cert = certificates .iter() .find(|cert| cert.certificate_id == certificate_id) - .ok_or("Certificate not found after submission")?; + .ok_or(Error::Certificate( + "Certificate not found after submission".to_string(), + ))?; let certificate = X509::from_der(&apple_cert.cert_content) - .map_err(|e| format!("Failed to parse certificate: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to parse certificate: {}", e)))?; // Write certificate to disk - let cert_pem = certificate - .to_pem() - .map_err(|e| format!("Failed to encode certificate to PEM: {}", e))?; + let cert_pem = certificate.to_pem().map_err(|e| { + Error::Certificate(format!("Failed to encode certificate to PEM: {}", e)) + })?; fs::write(&self.cert_file, cert_pem) - .map_err(|e| format!("Failed to save certificate file: {}", e))?; + .map_err(|e| Error::Certificate(format!("Failed to save certificate file: {}", e)))?; self.certificate = Some(certificate); diff --git a/src/device.rs b/src/device.rs index 2dee3cc..923a102 100644 --- a/src/device.rs +++ b/src/device.rs @@ -160,20 +160,3 @@ fn afc_upload_dir<'a>( Ok(()) }) } - -#[tauri::command] -pub async fn refresh_idevice(window: tauri::Window) { - match list_devices().await { - Ok(devices) => { - window - .emit("idevices", devices) - .expect("Failed to send devices"); - } - Err(e) => { - window - .emit("idevices", Vec::::new()) - .expect("Failed to send error"); - eprintln!("Failed to list devices: {}", e); - } - }; -} diff --git a/src/sideload.rs b/src/sideload.rs index a96427c..2152c5b 100644 --- a/src/sideload.rs +++ b/src/sideload.rs @@ -2,10 +2,9 @@ use crate::Error; use crate::{ + certificate::CertificateIdentity, + developer_session::DeveloperDeviceType, device::{DeviceInfo, install_app}, - sideloader::{ - certificate::CertificateIdentity, developer_session::DeveloperDeviceType, - }, }; use std::{io::Write, path::PathBuf};