diff --git a/ffi/src/installation_proxy.rs b/ffi/src/installation_proxy.rs index 6bdca82..a749ea4 100644 --- a/ffi/src/installation_proxy.rs +++ b/ffi/src/installation_proxy.rs @@ -109,11 +109,14 @@ pub unsafe extern "C" fn installation_proxy_get_apps( let app_type = if application_type.is_null() { None } else { - Some(unsafe { - std::ffi::CStr::from_ptr(application_type) - .to_string_lossy() - .into_owned() - }) + Some( + match unsafe { std::ffi::CStr::from_ptr(application_type) }.to_str() { + Ok(a) => a, + Err(_) => { + return ffi_err!(IdeviceError::InvalidCString); + } + }, + ) }; let bundle_ids = if bundle_identifiers.is_null() { @@ -125,9 +128,9 @@ pub unsafe extern "C" fn installation_proxy_get_apps( .map(|&s| { unsafe { std::ffi::CStr::from_ptr(s) } .to_string_lossy() - .into_owned() + .to_string() }) - .collect(), + .collect::>(), ) }; diff --git a/ffi/src/lockdown.rs b/ffi/src/lockdown.rs index b6470e6..81b0580 100644 --- a/ffi/src/lockdown.rs +++ b/ffi/src/lockdown.rs @@ -3,7 +3,7 @@ use std::ptr::null_mut; use idevice::{IdeviceError, IdeviceService, lockdown::LockdownClient, provider::IdeviceProvider}; -use plist_ffi::{PlistWrapper, plist_t}; +use plist_ffi::plist_t; use crate::{ IdeviceFfiError, IdeviceHandle, IdevicePairingFile, RUNTIME, ffi_err, @@ -183,18 +183,26 @@ pub unsafe extern "C" fn lockdownd_get_value( return ffi_err!(IdeviceError::FfiInvalidArg); } - let value = unsafe { std::ffi::CStr::from_ptr(key) } - .to_string_lossy() - .into_owned(); + let value = if key.is_null() { + None + } else { + Some(match unsafe { std::ffi::CStr::from_ptr(key) }.to_str() { + Ok(v) => v, + Err(_) => { + return ffi_err!(IdeviceError::InvalidCString); + } + }) + }; let domain = if domain.is_null() { None } else { - Some( - unsafe { std::ffi::CStr::from_ptr(domain) } - .to_string_lossy() - .into_owned(), - ) + Some(match unsafe { std::ffi::CStr::from_ptr(domain) }.to_str() { + Ok(v) => v, + Err(_) => { + return ffi_err!(IdeviceError::InvalidCString); + } + }) }; let res: Result = RUNTIME.block_on(async move { @@ -213,54 +221,6 @@ pub unsafe extern "C" fn lockdownd_get_value( } } -/// Gets all values from lockdownd -/// -/// # Arguments -/// * `client` - A valid LockdowndClient handle -/// * `out_plist` - Pointer to store the returned plist dictionary -/// -/// # Returns -/// An IdeviceFfiError on error, null on success -/// -/// # Safety -/// `client` must be a valid pointer to a handle allocated by this library -/// `out_plist` must be a valid pointer to store the plist -#[unsafe(no_mangle)] -pub unsafe extern "C" fn lockdownd_get_all_values( - client: *mut LockdowndClientHandle, - domain: *const libc::c_char, - out_plist: *mut plist_t, -) -> *mut IdeviceFfiError { - if out_plist.is_null() { - return ffi_err!(IdeviceError::FfiInvalidArg); - } - - let domain = if domain.is_null() { - None - } else { - Some( - unsafe { std::ffi::CStr::from_ptr(domain) } - .to_string_lossy() - .into_owned(), - ) - }; - - let res: Result = RUNTIME.block_on(async move { - let client_ref = unsafe { &mut (*client).0 }; - client_ref.get_all_values(domain).await - }); - - match res { - Ok(dict) => { - unsafe { - *out_plist = PlistWrapper::new_node(plist::Value::Dictionary(dict)).into_ptr(); - } - null_mut() - } - Err(e) => ffi_err!(e), - } -} - /// Frees a LockdowndClient handle /// /// # Arguments diff --git a/ffi/src/mobile_image_mounter.rs b/ffi/src/mobile_image_mounter.rs index 31ea76e..a539509 100644 --- a/ffi/src/mobile_image_mounter.rs +++ b/ffi/src/mobile_image_mounter.rs @@ -514,7 +514,7 @@ pub unsafe extern "C" fn image_mounter_query_nonce( let image_type = if !personalized_image_type.is_null() { let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(personalized_image_type) }; match image_type_cstr.to_str() { - Ok(s) => Some(s.to_string()), + Ok(s) => Some(s), Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), } } else { @@ -566,7 +566,7 @@ pub unsafe extern "C" fn image_mounter_query_personalization_identifiers( let image_type = if !image_type.is_null() { let image_type_cstr = unsafe { std::ffi::CStr::from_ptr(image_type) }; match image_type_cstr.to_str() { - Ok(s) => Some(s.to_string()), + Ok(s) => Some(s), Err(_) => return ffi_err!(IdeviceError::FfiInvalidArg), } } else { diff --git a/idevice/src/services/installation_proxy.rs b/idevice/src/services/installation_proxy.rs index f338d5d..3b4014f 100644 --- a/idevice/src/services/installation_proxy.rs +++ b/idevice/src/services/installation_proxy.rs @@ -98,10 +98,10 @@ impl InstallationProxyClient { /// ``` pub async fn get_apps( &mut self, - application_type: Option, + application_type: Option<&str>, bundle_identifiers: Option>, ) -> Result, IdeviceError> { - let application_type = application_type.unwrap_or("Any".to_string()); + let application_type = application_type.unwrap_or("Any"); let mut options = plist::Dictionary::new(); if let Some(ids) = bundle_identifiers { let ids = ids diff --git a/idevice/src/services/lockdown.rs b/idevice/src/services/lockdown.rs index 46a3589..2c1627d 100644 --- a/idevice/src/services/lockdown.rs +++ b/idevice/src/services/lockdown.rs @@ -86,16 +86,16 @@ impl LockdownClient { /// ``` pub async fn get_value( &mut self, - key: impl Into, - domain: Option, + key: Option<&str>, + domain: Option<&str>, ) -> Result { - let key = key.into(); - let mut request = plist::Dictionary::new(); request.insert("Label".into(), self.idevice.label.clone().into()); request.insert("Request".into(), "GetValue".into()); - request.insert("Key".into(), key.into()); + if let Some(key) = key { + request.insert("Key".into(), key.into()); + } if let Some(domain) = domain { request.insert("Domain".into(), domain.into()); } @@ -110,43 +110,6 @@ impl LockdownClient { } } - /// Retrieves all available values from the device - /// - /// # Returns - /// A dictionary containing all device values - /// - /// # Errors - /// Returns `IdeviceError` if: - /// - Communication fails - /// - The response is malformed - /// - /// # Example - /// ```rust - /// let all_values = client.get_all_values().await?; - /// for (key, value) in all_values { - /// println!("{}: {:?}", key, value); - /// } - /// ``` - pub async fn get_all_values( - &mut self, - domain: Option, - ) -> Result { - let mut request = plist::Dictionary::new(); - request.insert("Label".into(), self.idevice.label.clone().into()); - request.insert("Request".into(), "GetValue".into()); - if let Some(domain) = domain { - request.insert("Domain".into(), domain.into()); - } - - let message = plist::to_value(&request)?; - self.idevice.send_plist(message).await?; - let message: plist::Dictionary = self.idevice.read_plist().await?; - match message.get("Value") { - Some(m) => Ok(plist::from_value(m)?), - None => Err(IdeviceError::UnexpectedResponse), - } - } - /// Sets a value on the device /// /// # Arguments @@ -167,7 +130,7 @@ impl LockdownClient { &mut self, key: impl Into, value: Value, - domain: Option, + domain: Option<&str>, ) -> Result<(), IdeviceError> { let key = key.into(); @@ -321,7 +284,7 @@ impl LockdownClient { let host_id = host_id.into(); let system_buid = system_buid.into(); - let pub_key = self.get_value("DevicePublicKey", None).await?; + let pub_key = self.get_value(Some("DevicePublicKey"), None).await?; let pub_key = match pub_key.as_data().map(|x| x.to_vec()) { Some(p) => p, None => { @@ -330,7 +293,7 @@ impl LockdownClient { } }; - let wifi_mac = self.get_value("WiFiAddress", None).await?; + let wifi_mac = self.get_value(Some("WiFiAddress"), None).await?; let wifi_mac = match wifi_mac.as_string() { Some(w) => w, None => { diff --git a/idevice/src/services/mobile_image_mounter.rs b/idevice/src/services/mobile_image_mounter.rs index 78c71d6..2472719 100644 --- a/idevice/src/services/mobile_image_mounter.rs +++ b/idevice/src/services/mobile_image_mounter.rs @@ -113,7 +113,7 @@ impl ImageMounter { /// Returns `IdeviceError::NotFound` if image doesn't exist pub async fn lookup_image( &mut self, - image_type: impl Into, + image_type: impl Into<&str>, ) -> Result, IdeviceError> { let image_type = image_type.into(); let mut req = plist::Dictionary::new(); @@ -370,7 +370,7 @@ impl ImageMounter { /// Returns `IdeviceError` if query fails pub async fn query_nonce( &mut self, - personalized_image_type: Option, + personalized_image_type: Option<&str>, ) -> Result, IdeviceError> { let mut req = plist::Dictionary::new(); req.insert("Command".into(), "QueryNonce".into()); @@ -400,7 +400,7 @@ impl ImageMounter { /// Returns `IdeviceError` if query fails pub async fn query_personalization_identifiers( &mut self, - image_type: Option, + image_type: Option<&str>, ) -> Result { let mut req = plist::Dictionary::new(); req.insert("Command".into(), "QueryPersonalizationIdentifiers".into()); @@ -626,10 +626,7 @@ impl ImageMounter { request.insert("ApECID", unique_chip_id); request.insert( "ApNonce", - plist::Value::Data( - self.query_nonce(Some("DeveloperDiskImage".to_string())) - .await?, - ), + plist::Value::Data(self.query_nonce(Some("DeveloperDiskImage")).await?), ); request.insert("ApProductionMode", true); request.insert("ApSecurityDomain", 1); diff --git a/tools/src/ideviceinfo.rs b/tools/src/ideviceinfo.rs index 948a8c1..1ec95b7 100644 --- a/tools/src/ideviceinfo.rs +++ b/tools/src/ideviceinfo.rs @@ -67,7 +67,9 @@ async fn main() { println!( "{:?}", - lockdown_client.get_value("ProductVersion", None).await + lockdown_client + .get_value(Some("ProductVersion"), None) + .await ); println!( @@ -82,5 +84,5 @@ async fn main() { .await ); println!("{:?}", lockdown_client.idevice.get_type().await.unwrap()); - println!("{:#?}", lockdown_client.get_all_values(None).await); + println!("{:#?}", lockdown_client.get_value(None, None).await); } diff --git a/tools/src/instproxy.rs b/tools/src/instproxy.rs index e5f1980..f22b838 100644 --- a/tools/src/instproxy.rs +++ b/tools/src/instproxy.rs @@ -69,10 +69,7 @@ async fn main() { .await .expect("Unable to connect to instproxy"); if matches.subcommand_matches("lookup").is_some() { - let apps = instproxy_client - .get_apps(Some("User".to_string()), None) - .await - .unwrap(); + let apps = instproxy_client.get_apps(Some("User"), None).await.unwrap(); for app in apps.keys() { println!("{app}"); } diff --git a/tools/src/lockdown.rs b/tools/src/lockdown.rs index 00f3def..842c7b4 100644 --- a/tools/src/lockdown.rs +++ b/tools/src/lockdown.rs @@ -39,12 +39,7 @@ async fn main() { .subcommand( Command::new("get") .about("Gets a value") - .arg(arg!(-v --value "the value to get").required(true)) - .arg(arg!(-d --domain "the domain to get in").required(false)), - ) - .subcommand( - Command::new("get_all") - .about("Gets all") + .arg(arg!(-v --value "the value to get").required(false)) .arg(arg!(-d --domain "the domain to get in").required(false)), ) .subcommand( @@ -86,8 +81,8 @@ async fn main() { match matches.subcommand() { Some(("get", sub_m)) => { - let key = sub_m.get_one::("value").unwrap(); - let domain = sub_m.get_one::("domain").cloned(); + let key = sub_m.get_one::("value").map(|x| x.as_str()); + let domain = sub_m.get_one::("domain").map(|x| x.as_str()); match lockdown_client.get_value(key, domain).await { Ok(value) => { @@ -98,27 +93,18 @@ async fn main() { } } } - Some(("get_all", sub_m)) => { - let domain = sub_m.get_one::("domain").cloned(); - - match lockdown_client.get_all_values(domain).await { - Ok(value) => { - println!("{}", pretty_print_plist(&plist::Value::Dictionary(value))); - } - Err(e) => { - eprintln!("Error getting value: {e}"); - } - } - } Some(("set", sub_m)) => { let key = sub_m.get_one::("key").unwrap(); let value_str = sub_m.get_one::("value").unwrap(); - let domain = sub_m.get_one::("domain").cloned(); + let domain = sub_m.get_one::("domain"); let value = Value::String(value_str.clone()); - match lockdown_client.set_value(key, value, domain).await { + match lockdown_client + .set_value(key, value, domain.map(|x| x.as_str())) + .await + { Ok(()) => println!("Successfully set"), Err(e) => eprintln!("Error setting value: {e}"), } diff --git a/tools/src/mounter.rs b/tools/src/mounter.rs index 681705f..c59a472 100644 --- a/tools/src/mounter.rs +++ b/tools/src/mounter.rs @@ -89,7 +89,10 @@ async fn main() { .await .expect("Unable to connect to lockdown"); - let product_version = match lockdown_client.get_value("ProductVersion", None).await { + let product_version = match lockdown_client + .get_value(Some("ProductVersion"), None) + .await + { Ok(p) => p, Err(_) => { lockdown_client @@ -97,7 +100,7 @@ async fn main() { .await .unwrap(); lockdown_client - .get_value("ProductVersion", None) + .get_value(Some("ProductVersion"), None) .await .unwrap() } @@ -182,21 +185,22 @@ async fn main() { .await .expect("Unable to read signature"); - let unique_chip_id = match lockdown_client.get_value("UniqueChipID", None).await { - Ok(u) => u, - Err(_) => { - lockdown_client - .start_session(&provider.get_pairing_file().await.unwrap()) - .await - .expect("Unable to start session"); - lockdown_client - .get_value("UniqueChipID", None) - .await - .expect("Unable to get UniqueChipID") + let unique_chip_id = + match lockdown_client.get_value(Some("UniqueChipID"), None).await { + Ok(u) => u, + Err(_) => { + lockdown_client + .start_session(&provider.get_pairing_file().await.unwrap()) + .await + .expect("Unable to start session"); + lockdown_client + .get_value(Some("UniqueChipID"), None) + .await + .expect("Unable to get UniqueChipID") + } } - } - .as_unsigned_integer() - .expect("Unexpected value for chip IP"); + .as_unsigned_integer() + .expect("Unexpected value for chip IP"); mounter_client .mount_personalized_with_callback(