Improve error handling and fix compilation errors

This commit is contained in:
nab138
2025-08-06 22:13:57 -04:00
parent 9baf77f00e
commit e94d7b6448
6 changed files with 98 additions and 63 deletions

41
Cargo.lock generated
View File

@@ -677,6 +677,21 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" 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]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.31" version = "0.3.31"
@@ -684,6 +699,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink",
] ]
[[package]] [[package]]
@@ -692,6 +708,17 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 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]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.31" version = "0.3.31"
@@ -727,6 +754,7 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [ dependencies = [
"futures-channel",
"futures-core", "futures-core",
"futures-io", "futures-io",
"futures-macro", "futures-macro",
@@ -1061,6 +1089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b9d40e2753062fba4cac48cb459987dd9f66f6b777d90c546548f053bdd03c0" checksum = "7b9d40e2753062fba4cac48cb459987dd9f66f6b777d90c546548f053bdd03c0"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"chrono",
"env_logger", "env_logger",
"log", "log",
"plist", "plist",
@@ -1139,9 +1168,11 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
name = "isideload" name = "isideload"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"futures",
"hex", "hex",
"icloud_auth", "icloud_auth",
"idevice", "idevice",
"openssl",
"plist", "plist",
"serde", "serde",
"sha1", "sha1",
@@ -1531,6 +1562,15 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 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]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.109" version = "0.9.109"
@@ -1539,6 +1579,7 @@ checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
"openssl-src",
"pkg-config", "pkg-config",
"vcpkg", "vcpkg",
] ]

View File

@@ -3,6 +3,11 @@ name = "isideload"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
[features]
default = []
vendored-openssl = ["openssl/vendored"]
vendored-botan = ["icloud_auth/vendored-botan"]
[dependencies] [dependencies]
serde = { version = "1.0.219", features = ["derive"] } serde = { version = "1.0.219", features = ["derive"] }
plist = { version = "1.7.2" } plist = { version = "1.7.2" }
@@ -11,4 +16,6 @@ uuid = "1.17.0"
zip = "4.3.0" zip = "4.3.0"
hex = "0.4.3" hex = "0.4.3"
sha1 = "0.10.6" 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"

View File

@@ -3,7 +3,9 @@ name = "icloud_auth"
version = "0.1.0" version = "0.1.0"
edition = "2021" 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] [dependencies]
serde = { version = "1.0.219", features = ["derive"] } 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"]} omnisette = {path = "../omnisette", features = ["remote-anisette-v3"]}
thiserror = "1.0.58" thiserror = "1.0.58"
tokio = "1" tokio = "1"
botan = { version = "0.11.1", features = ["vendored"] } botan = { version = "0.11.1" }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
[dev-dependencies] [dev-dependencies]

View File

@@ -32,30 +32,29 @@ impl CertificateIdentity {
let hash_string = hex::encode(hasher.finalize()).to_lowercase(); let hash_string = hex::encode(hasher.finalize()).to_lowercase();
let key_path = configuration_path.join("keys").join(hash_string); let key_path = configuration_path.join("keys").join(hash_string);
fs::create_dir_all(&key_path) 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 key_file = key_path.join("key.pem");
let cert_file = key_path.join("cert.pem"); let cert_file = key_path.join("cert.pem");
let teams = dev_session let teams = dev_session.list_teams().await?;
.list_teams() let team = teams
.await .first()
.map_err(|e| format!("Failed to list teams: {:?}", e))?; .ok_or(Error::Certificate("No teams found".to_string()))?;
let team = teams.first().ok_or("No teams found")?;
let private_key = if key_file.exists() { let private_key = if key_file.exists() {
let key_data = fs::read_to_string(&key_file) 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()) 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 { } else {
let rsa = let rsa = Rsa::generate(2048)
Rsa::generate(2048).map_err(|e| format!("Failed to generate RSA key: {}", e))?; .map_err(|e| Error::Certificate(format!("Failed to generate RSA key: {}", e)))?;
let key = let key = PKey::from_rsa(rsa)
PKey::from_rsa(rsa).map_err(|e| format!("Failed to create private key: {}", e))?; .map_err(|e| Error::Certificate(format!("Failed to create private key: {}", e)))?;
let pem_data = key let pem_data = key
.private_key_to_pem_pkcs8() .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) 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 key
}; };
@@ -72,11 +71,12 @@ impl CertificateIdentity {
{ {
cert_identity.certificate = Some(cert.clone()); cert_identity.certificate = Some(cert.clone());
let cert_pem = cert let cert_pem = cert.to_pem().map_err(|e| {
.to_pem() Error::Certificate(format!("Failed to encode certificate to PEM: {}", e))
.map_err(|e| format!("Failed to encode certificate to PEM: {}", e))?; })?;
fs::write(&cert_identity.cert_file, cert_pem) fs::write(&cert_identity.cert_file, cert_pem).map_err(|e| {
.map_err(|e| format!("Failed to save certificate file: {}", e))?; Error::Certificate(format!("Failed to save certificate file: {}", e))
})?;
return Ok(cert_identity); 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( async fn request_new_certificate(
@@ -125,40 +127,40 @@ impl CertificateIdentity {
team: &DeveloperTeam, team: &DeveloperTeam,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut req_builder = X509ReqBuilder::new() let mut req_builder = X509ReqBuilder::new()
.map_err(|e| format!("Failed to create request builder: {}", e))?; .map_err(|e| Error::Certificate(format!("Failed to create request builder: {}", e)))?;
let mut name_builder = let mut name_builder = X509Name::builder()
X509Name::builder().map_err(|e| format!("Failed to create name builder: {}", e))?; .map_err(|e| Error::Certificate(format!("Failed to create name builder: {}", e)))?;
name_builder name_builder
.append_entry_by_text("C", "US") .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 name_builder
.append_entry_by_text("ST", "STATE") .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 name_builder
.append_entry_by_text("L", "LOCAL") .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 name_builder
.append_entry_by_text("O", "ORGNIZATION") .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 name_builder
.append_entry_by_text("CN", "CN") .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 req_builder
.set_subject_name(&name_builder.build()) .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 req_builder
.set_pubkey(&self.private_key) .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 req_builder
.sign(&self.private_key, MessageDigest::sha256()) .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 let csr_pem = req_builder
.build() .build()
.to_pem() .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 let certificate_id = dev_session
.submit_development_csr( .submit_development_csr(
@@ -181,23 +183,24 @@ impl CertificateIdentity {
let certificates = dev_session let certificates = dev_session
.list_all_development_certs(DeveloperDeviceType::Ios, team) .list_all_development_certs(DeveloperDeviceType::Ios, team)
.await .await?;
.map_err(|e| format!("Failed to list certificates: {:?}", e))?;
let apple_cert = certificates let apple_cert = certificates
.iter() .iter()
.find(|cert| cert.certificate_id == certificate_id) .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) 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 // Write certificate to disk
let cert_pem = certificate let cert_pem = certificate.to_pem().map_err(|e| {
.to_pem() Error::Certificate(format!("Failed to encode certificate to PEM: {}", e))
.map_err(|e| format!("Failed to encode certificate to PEM: {}", e))?; })?;
fs::write(&self.cert_file, cert_pem) 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); self.certificate = Some(certificate);

View File

@@ -160,20 +160,3 @@ fn afc_upload_dir<'a>(
Ok(()) 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::<DeviceInfo>::new())
.expect("Failed to send error");
eprintln!("Failed to list devices: {}", e);
}
};
}

View File

@@ -2,10 +2,9 @@
use crate::Error; use crate::Error;
use crate::{ use crate::{
certificate::CertificateIdentity,
developer_session::DeveloperDeviceType,
device::{DeviceInfo, install_app}, device::{DeviceInfo, install_app},
sideloader::{
certificate::CertificateIdentity, developer_session::DeveloperDeviceType,
},
}; };
use std::{io::Write, path::PathBuf}; use std::{io::Write, path::PathBuf};